Skip to content

Generate content in other languages (locale picker) (#166) - #232

Open
faisalahammad wants to merge 8 commits into
bordoni:mainfrom
faisalahammad:fix/166-generate-content-other-language
Open

Generate content in other languages (locale picker) (#166)#232
faisalahammad wants to merge 8 commits into
bordoni:mainfrom
faisalahammad:fix/166-generate-content-other-language

Conversation

@faisalahammad

@faisalahammad faisalahammad commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Closes #166.

Summary

Adds a locale picker to every FakerPress admin generation form and a matching locale REST param, so generated fake data reflects the selected language. English remains the default; unknown/omitted locales fall back to en_US.

A curated set of 10 locales ships in the prefixed Faker vendor: en_US, fr_FR, de_DE, es_ES, pt_BR, it_IT, nl_NL, ja_JP, zh_CN, ru_RU.

What changes

  • One source of truth for the locale list: fakerpress_get_available_locales() in src/functions/locale.php, required by Plugin.php.
  • Locale picker added to all 5 admin forms (Posts, Users, Terms, Comments, Attachments) — a native <select> defaulting to en_US.
  • REST locale arg added to all 5 generation endpoints via a shared get_locale_args() helper on Abstract_Endpoint. default => null, sanitized with sanitize_text_field, validated against the available-locales map.
  • Module wiring: each module's parse_request() reads locale from the request and calls set_locale() before any get_faker().
  • Abstract_Module::get_faker() builds the generator with the selected locale, falling back to Factory::DEFAULT_LOCALE (en_US) — never null (which would instantiate the abstract base Provider\Text and fatal).
  • Abstract_Module::set_locale() invalidates the cached generator when the locale actually changes, so any get_faker() call before the final set_locale() cannot pin the wrong locale for the request (modules are singletons; get_faker() is called from several sites).
  • Batching: Handles_Batching::calculate_batched_quantity() applies the locale before the first get_faker() call (qty-range numberBetween), so the batched-qty path doesn't cache en_US ahead of parse_request().
  • composer.json clean-faker-lang keeps the 10 shipped locales instead of stripping everything except en_US.

What the locale affects

Locale-scoped Faker providers: Person (names), Address, Company, PhoneNumber, and realText — these visibly change per locale. Useful for Users (display names), Comments (author names), Terms, and any meta using these providers.

Post title/content/excerpt use the base Lorem provider (sentence()/paragraphs()), which is locale-independent Latin pseudo-words by Faker's design — no locale ships a Lorem.php. This is stock Faker behavior, unchanged here. Generating truly localized post body text would require switching to realText(), which is out of scope for this issue.

Backward compatibility

  • REST endpoints accept a new optional locale param. Existing clients that omit it get en_US — identical to current behavior.
  • No signature change to get_faker(); it consults $this->locale internally.

Verification

Built a diagnostic probe that loads the active plugin's faker and runs Factory::create($locale) for every locale in the actual deployed environment (LocalWP). Output confirmed correct per-locale data in the prefixed vendor:

de_DE  name=Frau Prof. Dr. Karen Kluge   city=Neu-Ulm      (German)
fr_FR  name=Capucine-Louise Le Gall        city=Besson       (French)
ja_JP  name=原田 あすか                   city=吉本市        (Japanese)
zh_CN  name=娄桂珍                        city=福州          (Chinese)
es_ES  name=Ing. Ignacio Colón Segundo     city=Benavides... (Spanish)
ru_RU  name=Галина Львовна Елисеева       city=Ногинск       (Russian)

Manual smoke: admin form → pick locale → Generate; Users/Comments show locale-appropriate names. Invalid locale (xx_XX) → English fallback, no crash. PHPCS clean on changed lines (pre-existing hook-naming/docblock warnings untouched).

Notes for reviewers

  • One redundant-but-harmless explicit dependency: Post.php lists Lorem (already registered by Factory::create()). Left as-is.
  • Removed a dead duplicate src/FakerPress/functions/locale.php (identical to src/functions/locale.php, loaded nowhere) so the locale helper has a single source of truth.

- Add fakerpress_get_available_locales() helper with 10 curated locales
- Thread locale through Abstract_Module::get_faker() to Faker Factory
- Add locale param to all 5 REST endpoints (Posts, Users, Comments, Terms, Attachments)
- Add locale dropdown to all 5 admin form templates
- Update clean-faker-lang composer script to preserve locale directories

Falls back to en_US for unknown or unavailable locales.

Fixes bordoni#166
…pects it

The existing require_once in static_load() loads from src/functions/, not
src/FakerPress/functions/. locale.php must live at src/functions/ to match.
data-options is the Select2 attribute used for multiple-select fields.
The locale field is a single-select (native <select>), which reads
from 'options' via Field::parse(). Change the key so the dropdown
populates correctly.
Abstract_Endpoint and Abstract_Module import the function via
use function FakerPress\fakerpress_get_available_locales which
requires the function to be in the FakerPress namespace.
…er use (bordoni#166)

Three runtime defects found while testing non-English locale generation:

1. Stale prefixed vendor shipped only en_US. composer install re-ran
   clean-faker-lang (keeps the 10 curated locales) then Strauss, so all
   locale dirs now copy into vendor/prefixed/. No code change.

2. Abstract_Module::get_faker() fell back to Factory::create( null ) when
   locale was unset/invalid. null is falsy, so Factory resolved the base
   Provider\Text (abstract) instead of a locale Text class — fatal:
   "Cannot instantiate abstract class ...Provider\Text". Fall back to
   Factory::DEFAULT_LOCALE ('en_US') instead, matching the pre-feature
   Factory::create() no-arg default.

3. REST endpoints call calculate_batched_quantity() before
   Module::parse_request(), but the trait called get_faker() (for a qty
   range numberBetween) before parse_request() ran set_locale(). The faker
   was cached as en_US on first build and set_locale() arrived too late.
   Set the locale on the module at the top of the trait method, before any
   get_faker() call. parse_request()'s later set_locale() is idempotent.
get_faker() caches the Faker generator behind `if ( ! $this->faker )`.
set_locale() previously mutated $this->locale without nulling the cached
generator, so any get_faker() call before the final set_locale() pinned
the first locale for the rest of the request. Since modules are singletons
and get_faker() is called from multiple sites (batched qty, generation,
Meta, Attachment), an early call on the wrong locale would persist.

Null $this->faker in set_locale() whenever the locale actually changes,
so the generator rebuilds with the new locale on the next get_faker().
Idempotent on the happy path — one locale per request rebuilds once;
rebuild only happens on a genuine locale change.
src/FakerPress/functions/locale.php was an identical copy of
src/functions/locale.php and was never loaded — Plugin.php requires
src/functions/locale.php (line 170). Removes the dead duplicate so the
available-locales helper has one source of truth.
@faisalahammad
faisalahammad force-pushed the fix/166-generate-content-other-language branch from 8aea5c1 to e507d8e Compare July 17, 2026 18:41
PR bordoni#232 added set_locale( get( $request, 'locale', null ) ) to all five
module parse_request() methods, but Attachment.php was missing the
use function FakerPress\get; import that Post, User, Term, and Comment
already carry. The bare get() resolved to FakerPress\Module\get (undefined),
fatally erroring every Attachment generation request.

Error fixed:
- Call to undefined function FakerPress\Module\get() at Attachment.php:309

PHP 8.1+ compatible. All WPUnit checks passing.

Refs bordoni#166

@faisalahammad faisalahammad left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI Fix — 1 failure resolved

# File Error Fix
1 src/FakerPress/Module/Attachment.php:8 Call to undefined function FakerPress\Module\get() (Attachment generation, PHP 8.1/8.2/8.3 WPUnit) Add missing use function FakerPress\get; import

This PR added set_locale( get( \$request, 'locale', null ) ) to all five module parse_request() methods. Post, User, Term, and Comment each already imported the get() helper (declared in src/functions/variables.php, namespace FakerPress); Attachment was the only one missing the import, so its bare get() resolved to the undefined FakerPress\Module\get and fatality errored every attachment generation request.

PHPCS clean on the changed line (pre-existing violations in other files untouched). Other CI failures (PHPCS on src/templates/fields/* and src/data/readme.php, JS lint on src/resources/js/field.dependency.js) reproduce on main and are unrelated to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generate content in another language

1 participant