From 293c672fa7740a8e7b99ac8f431b842cf78b0738 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 30 Jan 2014 15:55:14 +1300 Subject: [PATCH] BUG Default Member.Locale now chooses a better default value when i18n.locale is not a valid translation This will resolve issues in cases where the site locale may be assigned a value that does not have an explicit translation. E.g. if the locale is en_NZ (and it's appropriate for this to be the assigned locale), Afrikaans will no longer be the default selected locale when creating members. Now en_US is chosen as a better fallback default. This is a minor ease of use fix that means fewer CMS users can be accidentally created in Afrikaans within NZ based sites. Test cases included. --- i18n/i18n.php | 18 ++++++++++++++++++ security/Member.php | 2 +- tests/i18n/i18nTest.php | 26 ++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/i18n/i18n.php b/i18n/i18n.php index 3ede6ee56..e0b121eda 100644 --- a/i18n/i18n.php +++ b/i18n/i18n.php @@ -2208,6 +2208,24 @@ class i18n extends Object implements TemplateGlobalProvider { return (array)Config::inst()->get('i18n', 'all_locales'); } + /** + * Matches a given locale with the closest translation available in the system + * + * @param string $locale locale code + * @return string Locale of closest available translation, if available + */ + public static function get_closest_translation($locale) { + + // Check if exact match + $pool = self::get_existing_translations(); + if(isset($pool[$locale])) return $locale; + + // Fallback to best locale for common language + $lang = self::get_lang_from_locale($locale); + $candidate = self::get_locale_from_lang($lang); + if(isset($pool[$candidate])) return $candidate; + } + /** * Searches the root-directory for module-directories * (identified by having a _config.php on their first directory-level). diff --git a/security/Member.php b/security/Member.php index cb16a8632..a0812565c 100644 --- a/security/Member.php +++ b/security/Member.php @@ -158,7 +158,7 @@ class Member extends DataObject implements TemplateGlobalProvider { */ public function populateDefaults() { parent::populateDefaults(); - $this->Locale = i18n::get_locale(); + $this->Locale = i18n::get_closest_translation(i18n::get_locale()); } public function requireDefaultRecords() { diff --git a/tests/i18n/i18nTest.php b/tests/i18n/i18nTest.php index fd98cbf82..1d2cc131c 100644 --- a/tests/i18n/i18nTest.php +++ b/tests/i18n/i18nTest.php @@ -102,6 +102,32 @@ class i18nTest extends SapphireTest { $this->assertTrue(isset($translations['de_DE']), 'Checking for de_DE translation'); } + public function testGetClosestTranslation() { + + // Validate necessary assumptions for this test + $translations = i18n::get_existing_translations(); + $this->assertTrue(isset($translations['en_US'])); + $this->assertTrue(isset($translations['en_GB'])); + $this->assertTrue(isset($translations['es_ES'])); + $this->assertTrue(isset($translations['es_AR'])); + $this->assertFalse(isset($translations['en_ZZ'])); + $this->assertFalse(isset($translations['es_ZZ'])); + $this->assertFalse(isset($translations['zz_ZZ'])); + + // Test indeterminate locales + $this->assertEmpty(i18n::get_closest_translation('zz_ZZ')); + + // Test english fallback + $this->assertEquals('en_US', i18n::get_closest_translation('en_US')); + $this->assertEquals('en_GB', i18n::get_closest_translation('en_GB')); + $this->assertEquals('en_US', i18n::get_closest_translation('en_ZZ')); + + // Test spanish fallbacks + $this->assertEquals('es_AR', i18n::get_closest_translation('es_AR')); + $this->assertEquals('es_ES', i18n::get_closest_translation('es_ES')); + $this->assertEquals('es_ES', i18n::get_closest_translation('es_XX')); + } + public function testDataObjectFieldLabels() { $oldLocale = i18n::get_locale(); i18n::set_locale('de_DE');