diff --git a/app/Console/Commands/Dev/ExportLanguages.php b/app/Console/Commands/Dev/ExportLanguages.php index b98e9c46a..ee1843fcd 100644 --- a/app/Console/Commands/Dev/ExportLanguages.php +++ b/app/Console/Commands/Dev/ExportLanguages.php @@ -91,9 +91,32 @@ class ExportLanguages extends Command * * @param array $langs Valid locale codes (lang/ folders). */ + /** + * Display-name overrides for locale codes that ICU cannot resolve + * correctly. Crowdin uses some non-standard codes (e.g. custom + * languages) that would otherwise render as the wrong language or as + * the raw code via locale_get_display_name(). + * + * @var array + */ + protected const LOCALE_OVERRIDES = [ + // Crowdin custom "Pirate English". BCP-47 would read en-Pirate as + // English, and the old en-PT code collided with English (Portugal). + 'en-Pirate' => ['name' => 'English (Pirate)', 'nativeName' => 'English (Pirate)'], + + // Klingon. 'tlh' is valid BCP-47 (ICU renders "Klingon"), but ICU has + // no native-name form, so pin both for a consistent label. Mapped from + // Crowdin's tlh-AA (AA is a fake region) via crowdin.yml. + 'tlh' => ['name' => 'Klingon', 'nativeName' => 'tlhIngan Hol'], + ]; + protected function writeLocalesManifest(array $langs): void { $locales = array_map(function ($code) { + if (isset(self::LOCALE_OVERRIDES[$code])) { + return array_merge(['code' => $code], self::LOCALE_OVERRIDES[$code]); + } + return [ 'code' => $code, 'name' => locale_get_display_name($code, 'en'), diff --git a/crowdin.yml b/crowdin.yml index b50dfe919..58eb87781 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -3,26 +3,40 @@ api_token_env: CROWDIN_PERSONAL_TOKEN base_path: '.' preserve_hierarchy: true +# Map Crowdin's non-standard locale codes to clean folder names. Avoids the +# en-PT ↔ English (Portugal) BCP-47 collision and the fake tlh-AA region. +# Applied per file entry below via the *locale_mapping anchor. +# en-PT (Pirate English) -> en-Pirate +# tlh-AA (Klingon) -> tlh (tlh is valid BCP-47; AA is a fake region) + files: - source: /lang/en-US/auth.php translation: /lang/%locale%/auth.php skip_untranslated_strings: true + languages_mapping: &locale_mapping + locale: + en-PT: en-Pirate + tlh-AA: tlh - source: /lang/en-US/exception.php translation: /lang/%locale%/exception.php skip_untranslated_strings: true + languages_mapping: *locale_mapping - source: /lang/en-US/helpcenter.php translation: /lang/%locale%/helpcenter.php skip_untranslated_strings: true + languages_mapping: *locale_mapping - source: /lang/en-US/navmenu.php translation: /lang/%locale%/navmenu.php skip_untranslated_strings: true + languages_mapping: *locale_mapping - source: /lang/en-US/notification.php translation: /lang/%locale%/notification.php skip_untranslated_strings: true + languages_mapping: *locale_mapping # - source: /lang/en-US/pagination.php # translation: /lang/%locale%/pagination.php @@ -31,22 +45,27 @@ files: - source: /lang/en-US/passwords.php translation: /lang/%locale%/passwords.php skip_untranslated_strings: true + languages_mapping: *locale_mapping - source: /lang/en-US/profile.php translation: /lang/%locale%/profile.php skip_untranslated_strings: true + languages_mapping: *locale_mapping - source: /lang/en-US/settings.php translation: /lang/%locale%/settings.php skip_untranslated_strings: true + languages_mapping: *locale_mapping - source: /lang/en-US/site.php translation: /lang/%locale%/site.php skip_untranslated_strings: true + languages_mapping: *locale_mapping - source: /lang/en-US/timeline.php translation: /lang/%locale%/timeline.php skip_untranslated_strings: true + languages_mapping: *locale_mapping # - source: /lang/en-US/validation.php # translation: /lang/%locale%/validation.php @@ -55,3 +74,4 @@ files: - source: /lang/en-US/web.php translation: /lang/%locale%/web.php skip_untranslated_strings: true + languages_mapping: *locale_mapping