Documentation · Developer Documentation

Internationalization For Developers

This document describes how the ADP Car Market Hub plugin handles internationalization (i18n) for translators and contributors. It covers the text domain, the loading mechanism, the translation files shipped with the plugin, the tooling used to generate the POT file, and the conventions to follow when adding new translatable strings.

When to use this document

Read this document when you need to:

  • Add a new translatable string to PHP, JavaScript or template code.
  • Regenerate the POT file after adding strings.
  • Provide a new language translation for the plugin.
  • Understand why a particular admin or front-end string is or is not translated.

For translator-facing notes, see the repository's README-i18n.md.

Overview

The plugin uses the standard WordPress i18n APIs (__(), _e(), _n(), _x(), esc_html__(), esc_attr__(), esc_html_e(), esc_attr_e(), …) with a single text domain.

  • Text domain: adp-car-market-hub.
  • Domain path: /languages (declared in the plugin header).
  • Loader: load_plugin_textdomain( 'adp-car-market-hub', false, '/languages' ) is called from a function hooked to plugins_loaded at priority 1, so translations are loaded before the plugin's own init work runs.

JavaScript strings used by the plugin's bundled scripts are pre-translated in PHP and passed to JavaScript through wp_localize_script(). The plugin does not currently rely on wp_set_script_translations() and the JSON translation workflow associated with it.

Requirements or prerequisites

  • Source files written using the WordPress i18n functions with 'adp-car-market-hub' as the text domain.
  • WP-CLI installed when regenerating the POT file (the helper script uses wp i18n make-pot).
  • A POEdit-compatible editor (or any tool that understands GNU gettext) for editing .po files.

Translation files shipped with the plugin

All translation files live under /languages and follow the standard WordPress naming convention.

FilePurpose
adp-car-market-hub.potTranslation template (source for new translations).
adp-car-market-hub-de_DE.po and .moGerman (Germany), informal address.
adp-car-market-hub-de_DE_formal.po and .moGerman (Germany), formal address.
adp-car-market-hub-de_AT.po and .moGerman (Austria).
adp-car-market-hub-de_CH.po and .moGerman (Switzerland).
adp-car-market-hub-fr_FR.po and .moFrench (France).
adp-car-market-hub-it_IT.po and .moItalian (Italy).
adp-car-market-hub-es_ES.po and .moSpanish (Spain).
adp-car-market-hub-nl_NL.po and .moDutch (Netherlands).

Each shipped locale includes both a .po source and a compiled .mo. The list above reflects the files currently present; verify the latest set in the /languages folder before publishing.

Tooling

Regenerating the POT file

A helper script is provided in the repository's bin/ directory. It calls WP-CLI's i18n make-pot command and excludes folders that should not be scanned (.git, node_modules, vendor, tests, bin).

To run it:

  1. Make sure WP-CLI is installed and available on PATH.
  2. From the repository root, execute the script.
  3. The updated .pot file is written to languages/adp-car-market-hub.pot.

Compiling .mo files

After editing a .po file, compile a matching .mo with your editor (POEdit's "Save" produces both files automatically) or with msgfmt from gettext.

Step by step instructions

Add a translatable string in PHP

  1. Wrap the string with the appropriate WordPress i18n function and pass 'adp-car-market-hub' as the text domain. For example, __( 'Lead saved.', 'adp-car-market-hub' ) or esc_html__( 'Vehicles', 'adp-car-market-hub' ).
  2. Where the string is concatenated with HTML, prefer the esc_*__ and esc_*_e variants to combine escaping and translation in one call.
  3. For pluralisation, use _n() or _nx(). For context disambiguation, use _x().
  4. Regenerate the POT file (see above) so translators can pick up the new string.

Add a translatable string used in JavaScript

  1. Translate the string in PHP first (__( 'Sending…', 'adp-car-market-hub' )).
  2. Pass it to JavaScript through the wp_localize_script() array used by the relevant handle. See Frontend Assets and Admin Assets for the localised objects already in use (for example AS24CI, as24ciCompare, AS24CI_LEADS, AS24CI_BATCH).
  3. Read the value from the corresponding global in the JavaScript code.

Provide a new translation

  1. Copy languages/adp-car-market-hub.pot to languages/adp-car-market-hub-<locale>.po using the WordPress locale code (for example es_ES).
  2. Translate the strings.
  3. Compile the .mo file alongside the .po.
  4. Open a pull request with both files.

Operational notes

  • Single text domain. Every translatable string in the plugin uses 'adp-car-market-hub'. Do not introduce additional text domains.
  • Keep the POT current. When a contributor adds or removes strings, regenerate the POT file in the same change so that translation files can be merged cleanly.
  • JavaScript strings. Because JS strings are translated via wp_localize_script(), they appear in the POT only when the corresponding PHP-side __() call is present. Always translate JS strings in PHP first.
  • Locale-aware formatting. Number and currency formatting is handled by the plugin's own locale helpers. Use the helpers exposed by the plugin rather than re-implementing locale logic in your own code.
  • WordPress translation platform. The plugin can be translated outside of the repository through any standard gettext workflow. There is no specific external translation service required.

Troubleshooting

  • A string is not translated on the front end. Confirm the string is wrapped in an i18n function with the correct text domain. Confirm the language is installed in WordPress (Settings → General → Site Language) and that a .mo file for that locale exists in /languages.
  • Newly added strings do not appear in the POT. Re-run the POT helper script. Verify your file is not under one of the excluded folders.
  • JS-side text is still in English after PHP translation. Confirm the string is being passed through wp_localize_script() for the relevant handle. The plugin does not auto-detect untranslated JS strings.
  • Plurals fall back to the singular form. Use _n() (or _nx() for context) instead of __() for any string that varies with a count.
  • Verify behaviour in the current plugin version before publishing a custom integration. Localised JavaScript object names can evolve between releases.