diff --git a/infra/LocaleGenerator.php b/infra/LocaleGenerator.php index edbe32bc..139733cc 100644 --- a/infra/LocaleGenerator.php +++ b/infra/LocaleGenerator.php @@ -108,6 +108,8 @@ class LocaleGenerator $errorCodeTranslation = "{$errorCode} = {$translationValue}" . PHP_EOL; fwrite($configFile, $errorCodeTranslation); } else { + $errorCodeTranslation = "{$errorCode}" . PHP_EOL; + fwrite($configFile, $errorCodeTranslation); echo "No {$language} translation available for error code {$errorCode}", PHP_EOL; } } diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 39077c17..354e4a88 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -2914,6 +2914,21 @@ class Calculation return self::$localeLanguage; } + private function getLocaleFile(string $localeDir, string $locale, string $language, string $file) + { + $localeFileName = $localeDir . str_replace('_', DIRECTORY_SEPARATOR, $locale) . + DIRECTORY_SEPARATOR . $file; + if (!file_exists($localeFileName)) { + // If there isn't a locale specific file, look for a language specific file + $localeFileName = $localeDir . $language . DIRECTORY_SEPARATOR . $file; + if (!file_exists($localeFileName)) { + throw new Exception('Locale file not found'); + } + } + + return $localeFileName; + } + /** * Set the locale code. * @@ -2921,7 +2936,7 @@ class Calculation * * @return bool */ - public function setLocale($locale) + public function setLocale(string $locale) { // Identify our locale and language $language = $locale = strtolower($locale); @@ -2931,23 +2946,24 @@ class Calculation if (count(self::$validLocaleLanguages) == 1) { self::loadLocales(); } + // Test whether we have any language data for this language (any locale) if (in_array($language, self::$validLocaleLanguages)) { // initialise language/locale settings self::$localeFunctions = []; self::$localeArgumentSeparator = ','; self::$localeBoolean = ['TRUE' => 'TRUE', 'FALSE' => 'FALSE', 'NULL' => 'NULL']; - // Default is English, if user isn't requesting english, then read the necessary data from the locale files - if ($locale != 'en_us') { + + // Default is US English, if user isn't requesting US english, then read the necessary data from the locale files + if ($locale !== 'en_us') { + $localeDir = implode(DIRECTORY_SEPARATOR, [__DIR__, 'locale', null]); // Search for a file with a list of function names for locale - $functionNamesFile = __DIR__ . '/locale/' . str_replace('_', DIRECTORY_SEPARATOR, $locale) . DIRECTORY_SEPARATOR . 'functions'; - if (!file_exists($functionNamesFile)) { - // If there isn't a locale specific function file, look for a language specific function file - $functionNamesFile = __DIR__ . '/locale/' . $language . DIRECTORY_SEPARATOR . 'functions'; - if (!file_exists($functionNamesFile)) { - return false; - } + try { + $functionNamesFile = $this->getLocaleFile($localeDir, $locale, $language, 'functions'); + } catch (Exception $e) { + return false; } + // Retrieve the list of locale or language specific function names $localeFunctions = file($functionNamesFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($localeFunctions as $localeFunction) { @@ -2967,24 +2983,24 @@ class Calculation self::$localeBoolean['FALSE'] = self::$localeFunctions['FALSE']; } - $configFile = __DIR__ . '/locale/' . str_replace('_', DIRECTORY_SEPARATOR, $locale) . DIRECTORY_SEPARATOR . 'config'; - if (!file_exists($configFile)) { - $configFile = __DIR__ . '/locale/' . $language . DIRECTORY_SEPARATOR . 'config'; + try { + $configFile = $this->getLocaleFile($localeDir, $locale, $language, 'config'); + } catch (Exception $e) { + return false; } - if (file_exists($configFile)) { - $localeSettings = file($configFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); - foreach ($localeSettings as $localeSetting) { - [$localeSetting] = explode('##', $localeSetting); // Strip out comments - if (strpos($localeSetting, '=') !== false) { - [$settingName, $settingValue] = array_map('trim', explode('=', $localeSetting)); - $settingName = strtoupper($settingName); - if ($settingValue !== '') { - switch ($settingName) { - case 'ARGUMENTSEPARATOR': - self::$localeArgumentSeparator = $settingValue; - break; - } + $localeSettings = file($configFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + foreach ($localeSettings as $localeSetting) { + [$localeSetting] = explode('##', $localeSetting); // Strip out comments + if (strpos($localeSetting, '=') !== false) { + [$settingName, $settingValue] = array_map('trim', explode('=', $localeSetting)); + $settingName = strtoupper($settingName); + if ($settingValue !== '') { + switch ($settingName) { + case 'ARGUMENTSEPARATOR': + self::$localeArgumentSeparator = $settingValue; + + break; } } } diff --git a/src/PhpSpreadsheet/Calculation/locale/cs/config b/src/PhpSpreadsheet/Calculation/locale/cs/config index 015bbd6e..49f40fcb 100644 --- a/src/PhpSpreadsheet/Calculation/locale/cs/config +++ b/src/PhpSpreadsheet/Calculation/locale/cs/config @@ -11,6 +11,7 @@ ArgumentSeparator = ; ## ## Error Codes ## +NULL DIV0 = #DĚLENÍ_NULOU! VALUE = #HODNOTA! REF = #ODKAZ! diff --git a/src/PhpSpreadsheet/Calculation/locale/da/config b/src/PhpSpreadsheet/Calculation/locale/da/config index b0747c9d..284b2490 100644 --- a/src/PhpSpreadsheet/Calculation/locale/da/config +++ b/src/PhpSpreadsheet/Calculation/locale/da/config @@ -12,7 +12,9 @@ ArgumentSeparator = ; ## Error Codes ## NULL = #NUL! +DIV0 VALUE = #VÆRDI! REF = #REFERENCE! NAME = #NAVN? +NUM NA = #I/T diff --git a/src/PhpSpreadsheet/Calculation/locale/de/config b/src/PhpSpreadsheet/Calculation/locale/de/config index 353cad2e..4ca2b82b 100644 --- a/src/PhpSpreadsheet/Calculation/locale/de/config +++ b/src/PhpSpreadsheet/Calculation/locale/de/config @@ -11,7 +11,10 @@ ArgumentSeparator = ; ## ## Error Codes ## +NULL +DIV0 VALUE = #WERT! REF = #BEZUG! +NAME NUM = #ZAHL! NA = #NV diff --git a/src/PhpSpreadsheet/Calculation/locale/es/config b/src/PhpSpreadsheet/Calculation/locale/es/config index 794b813c..fe044efa 100644 --- a/src/PhpSpreadsheet/Calculation/locale/es/config +++ b/src/PhpSpreadsheet/Calculation/locale/es/config @@ -17,3 +17,4 @@ VALUE = #¡VALOR! REF = #¡REF! NAME = #¿NOMBRE? NUM = #¡NUM! +NA diff --git a/src/PhpSpreadsheet/Calculation/locale/fr/config b/src/PhpSpreadsheet/Calculation/locale/fr/config index eb400aae..bdac4121 100644 --- a/src/PhpSpreadsheet/Calculation/locale/fr/config +++ b/src/PhpSpreadsheet/Calculation/locale/fr/config @@ -12,6 +12,9 @@ ArgumentSeparator = ; ## Error Codes ## NULL = #NUL! +DIV0 VALUE = #VALEUR! +REF NAME = #NOM? NUM = #NOMBRE! +NA diff --git a/src/PhpSpreadsheet/Calculation/locale/it/config b/src/PhpSpreadsheet/Calculation/locale/it/config index 62779f2c..5c1e4955 100644 --- a/src/PhpSpreadsheet/Calculation/locale/it/config +++ b/src/PhpSpreadsheet/Calculation/locale/it/config @@ -11,7 +11,10 @@ ArgumentSeparator = ; ## ## Error Codes ## +NULL +DIV0 VALUE = #VALORE! REF = #RIF! NAME = #NOME? +NUM NA = #N/D diff --git a/src/PhpSpreadsheet/Calculation/locale/nb/config b/src/PhpSpreadsheet/Calculation/locale/nb/config index c6458095..a7f3be17 100644 --- a/src/PhpSpreadsheet/Calculation/locale/nb/config +++ b/src/PhpSpreadsheet/Calculation/locale/nb/config @@ -11,6 +11,10 @@ ArgumentSeparator = ; ## ## Error Codes ## +NULL +DIV0 VALUE = #VERDI! +REF NAME = #NAVN? +NUM NA = #N/D diff --git a/src/PhpSpreadsheet/Calculation/locale/pt/br/config b/src/PhpSpreadsheet/Calculation/locale/pt/br/config index 2ad8b6c8..c39057c7 100644 --- a/src/PhpSpreadsheet/Calculation/locale/pt/br/config +++ b/src/PhpSpreadsheet/Calculation/locale/pt/br/config @@ -12,7 +12,9 @@ ArgumentSeparator = ; ## Error Codes ## NULL = #NULO! +DIV0 VALUE = #VALOR! +REF NAME = #NOME? NUM = #NÚM! NA = #N/D diff --git a/src/PhpSpreadsheet/Calculation/locale/pt/config b/src/PhpSpreadsheet/Calculation/locale/pt/config index 5162eb91..e661830b 100644 --- a/src/PhpSpreadsheet/Calculation/locale/pt/config +++ b/src/PhpSpreadsheet/Calculation/locale/pt/config @@ -12,7 +12,9 @@ ArgumentSeparator = ; ## Error Codes ## NULL = #NULO! +DIV0 VALUE = #VALOR! +REF NAME = #NOME? NUM = #NÚM! NA = #N/D diff --git a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php index 4796c7b6..296a3b0f 100644 --- a/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/CalculationTest.php @@ -95,6 +95,12 @@ class CalculationTest extends TestCase self::assertTrue($calculation->setLocale($locale)); } + public function testInvalidLocaleReturnsFalse(): void + { + $calculation = Calculation::getInstance(); + self::assertFalse($calculation->setLocale('xx')); + } + public function providerCanLoadAllSupportedLocales(): array { return [