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 toplugins_loadedat priority 1, so translations are loaded before the plugin's owninitwork 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
.pofiles.
Translation files shipped with the plugin
All translation files live under /languages and follow the standard WordPress naming convention.
| File | Purpose |
|---|---|
adp-car-market-hub.pot | Translation template (source for new translations). |
adp-car-market-hub-de_DE.po and .mo | German (Germany), informal address. |
adp-car-market-hub-de_DE_formal.po and .mo | German (Germany), formal address. |
adp-car-market-hub-de_AT.po and .mo | German (Austria). |
adp-car-market-hub-de_CH.po and .mo | German (Switzerland). |
adp-car-market-hub-fr_FR.po and .mo | French (France). |
adp-car-market-hub-it_IT.po and .mo | Italian (Italy). |
adp-car-market-hub-es_ES.po and .mo | Spanish (Spain). |
adp-car-market-hub-nl_NL.po and .mo | Dutch (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:
- Make sure WP-CLI is installed and available on
PATH. - From the repository root, execute the script.
- The updated
.potfile is written tolanguages/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
- 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' )oresc_html__( 'Vehicles', 'adp-car-market-hub' ). - Where the string is concatenated with HTML, prefer the
esc_*__andesc_*_evariants to combine escaping and translation in one call. - For pluralisation, use
_n()or_nx(). For context disambiguation, use_x(). - Regenerate the POT file (see above) so translators can pick up the new string.
Add a translatable string used in JavaScript
- Translate the string in PHP first (
__( 'Sending…', 'adp-car-market-hub' )). - 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 exampleAS24CI,as24ciCompare,AS24CI_LEADS,AS24CI_BATCH). - Read the value from the corresponding global in the JavaScript code.
Provide a new translation
- Copy
languages/adp-car-market-hub.pottolanguages/adp-car-market-hub-<locale>.pousing the WordPress locale code (for examplees_ES). - Translate the strings.
- Compile the
.mofile alongside the.po. - 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
.mofile 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.