From ddcae31d48bd2f7d94cd3b2d120c1cea3496f808 Mon Sep 17 00:00:00 2001 From: Mathias Kresin Date: Fri, 30 Jan 2015 19:45:23 +0100 Subject: [PATCH 1/2] add multiple plural support for translations fixes #242 --- controllers/common.php | 5 +--- lib/Translator.php | 29 +++++++++++++------ lib/helpers.php | 12 ++++---- locales/cs_CZ/translations.php | 10 ++----- locales/de_DE/translations.php | 22 ++++++--------- locales/en_US/translations.php | 12 ++++++++ locales/es_ES/translations.php | 10 ++----- locales/fr_FR/translations.php | 20 +++++-------- locales/it_IT/translations.php | 10 ++----- locales/pt_BR/translations.php | 22 ++++++--------- locales/zh_CN/translations.php | 8 +----- models/config.php | 14 +++++----- scripts/sync-locales.php | 51 ++++++++++++++++++++++++++++------ 13 files changed, 120 insertions(+), 105 deletions(-) create mode 100644 locales/en_US/translations.php diff --git a/controllers/common.php b/controllers/common.php index 58c1fd9..ee03a4f 100644 --- a/controllers/common.php +++ b/controllers/common.php @@ -40,10 +40,7 @@ Router\before(function($action) { // Load translations $language = Model\Config\get('language') ?: 'en_US'; - - if ($language !== 'en_US') { - Translator\load($language); - } + Translator\load($language); // Set timezone date_default_timezone_set(Model\Config\get('timezone') ?: 'UTC'); diff --git a/lib/Translator.php b/lib/Translator.php index 77c35ed..393bf78 100644 --- a/lib/Translator.php +++ b/lib/Translator.php @@ -10,7 +10,7 @@ namespace Translator { $args = \func_get_args(); \array_shift($args); - \array_unshift($args, get($identifier, $identifier)); + \array_unshift($args, get($identifier, $identifier, $args)); foreach ($args as &$arg) { $arg = htmlspecialchars($arg, ENT_QUOTES, 'UTF-8', false); @@ -76,23 +76,36 @@ namespace Translator { $format = preg_replace('#(? 1 ? 's' : '').' ago', $diff); + if ($diff < 60) return \t('%d second ago', $diff); $diff = floor($diff / 60); - if ($diff < 60) return \t('%d minute'.($diff > 1 ? 's' : '').' ago', $diff); + if ($diff < 60) return \t('%d minute ago', $diff); $diff = floor($diff / 60); - if ($diff < 24) return \t('%d hour'.($diff > 1 ? 's' : '').' ago', $diff); + if ($diff < 24) return \t('%d hour ago', $diff); $diff = floor($diff / 24); - if ($diff < 7) return \t('%d day'.($diff > 1 ? 's' : '').' ago', $diff); + if ($diff < 7) return \t('%d day ago', $diff); $diff = floor($diff / 7); - if ($diff < 4) return \t('%d week'.($diff > 1 ? 's' : '').' ago', $diff); + if ($diff < 4) return \t('%d week ago', $diff); $diff = floor($diff / 4); - if ($diff < 12) return \t('%d month'.($diff > 1 ? 's' : '').' ago', $diff); + if ($diff < 12) return \t('%d month ago', $diff); return \dt($fallback_date_format, $timestamp); } diff --git a/locales/cs_CZ/translations.php b/locales/cs_CZ/translations.php index eb7e743..43d2747 100644 --- a/locales/cs_CZ/translations.php +++ b/locales/cs_CZ/translations.php @@ -1,6 +1,7 @@ function($n) { return (($n==1) ? 0 : (($n>=2 && $n<=4) ? 1 : 2)); }, // 'attachment' => '', // 'When there is nothing to read, redirect me to this page' => '', // 'There is nothing new to read, enjoy your favorites articles!' => '', @@ -62,8 +63,7 @@ return array( 'Do not fetch the content of articles' => 'Nestahovat obsah článků', 'Remove automatically read items' => 'Automaticky odstraňovat přečtené stránky', 'Never' => 'Nikdy', - 'After %d day' => 'Po %d dni', - 'After %d days' => 'Po %d dnech', + 'After %d day' => array('Po %d dni', 'Po %d dnech', 'Po %d dnech'), 'unread' => 'nepřečtené', 'Unread' => 'Nepřečtené', 'bookmark' => 'přidat do záložek', @@ -147,17 +147,11 @@ return array( 'Show help' => 'Zobrazit nápovědu', 'Close help' => 'Zavřít nápovědu', // '%d second ago' => '', - // '%d seconds ago' => '', // '%d minute ago' => '', - // '%d minutes ago' => '', // '%d hour ago' => '', - // '%d hours ago' => '', // '%d day ago' => '', - // '%d days ago' => '', // '%d week ago' => '', - // '%d weeks ago' => '', // '%d month ago' => '', - // '%d months ago' => '', // 'Timezone' => '', // 'Update all subscriptions' => '', // 'Auto-Update URL' => '', diff --git a/locales/de_DE/translations.php b/locales/de_DE/translations.php index 870b7fd..8a284b1 100644 --- a/locales/de_DE/translations.php +++ b/locales/de_DE/translations.php @@ -1,6 +1,7 @@ function($n) { return ($n != 1); }, 'attachment' => 'Anhang', 'When there is nothing to read, redirect me to this page' => 'Wenn es nichts zu lesen gibt, leite mich auf diese Seite weiter', 'There is nothing new to read, enjoy your favorites articles!' => 'Es gibt nichts zu lesen, genieße deine Favoriten!', @@ -62,8 +63,7 @@ return array( 'Do not fetch the content of articles' => 'Den Inhalt der Artikel nicht auslesen', 'Remove automatically read items' => 'Gelesene Einträge automatisch entfernen', 'Never' => 'Niemals', - 'After %d day' => 'Nach %d Tag', - 'After %d days' => 'Nach %d Tagen', + 'After %d day' => array('Nach %d Tag', 'Nach %d Tagen'), 'unread' => 'ungelesen', 'Unread' => 'Ungelesen', 'bookmark' => 'Lesezeichen', @@ -146,18 +146,12 @@ return array( 'Nothing to read, do you want to %supdate your subscriptions%s?' => 'Nichts zu lesen, möchtest du %sdeine Abonnements aktualisieren%s?', 'Show help' => 'Hilfe zeigen', 'Close help' => 'Hilfe schließen', - '%d second ago' => 'Vor %d Sekunde', - '%d seconds ago' => 'Vor %d Sekunden', - '%d minute ago' => 'Vor %d Minute', - '%d minutes ago' => 'Vor %d Minuten', - '%d hour ago' => 'Vor %d Stunde', - '%d hours ago' => 'Vor %d Stunden', - '%d day ago' => 'Vor %d Tag', - '%d days ago' => 'Vor %d Tagen', - '%d week ago' => 'Vor %d Woche', - '%d weeks ago' => 'Vor %d Wochen', - '%d month ago' => 'Vor %d Monat', - '%d months ago' => 'Vor %d Monaten', + '%d second ago' => array('Vor %d Sekunde', 'Vor %d Sekunden'), + '%d minute ago' => array('Vor %d Minute', 'Vor %d Minuten'), + '%d hour ago' => array('Vor %d Stunde', 'Vor %d Stunden'), + '%d day ago' => array('Vor %d Tag', 'Vor %d Tagen'), + '%d week ago' => array('Vor %d Woche', 'Vor %d Wochen'), + '%d month ago' => array('Vor %d Monat', 'Vor %d Monaten'), 'Timezone' => 'Zeitzone', 'Update all subscriptions' => 'Alle Abonnements aktualisieren', 'Auto-Update URL' => 'Auto-Update URL', diff --git a/locales/en_US/translations.php b/locales/en_US/translations.php new file mode 100644 index 0000000..4bd7670 --- /dev/null +++ b/locales/en_US/translations.php @@ -0,0 +1,12 @@ + function($n) { return ($n != 1); }, + 'After %d day' => array('After %d day', 'After %d days'), + '%d second ago' => array('%d second ago', '%d seconds ago'), + '%d minute ago' => array('%d minute ago', '%d minutes ago'), + '%d hour ago' => array('%d hour ago', '%d hours ago'), + '%d day ago' => array('%d day ago', '%d days ago'), + '%d week ago' => array('%d week ago', '%d weeks ago'), + '%d month ago' => array('%d month ago', '%d months ago'), +); diff --git a/locales/es_ES/translations.php b/locales/es_ES/translations.php index 5551e71..b946bfd 100644 --- a/locales/es_ES/translations.php +++ b/locales/es_ES/translations.php @@ -1,6 +1,7 @@ function($n) { return ($n != 1); }, // 'attachment' => '', 'When there is nothing to read, redirect me to this page' => 'Cuando no hay nada que leer, redirigirme a esta página', 'There is nothing new to read, enjoy your favorites articles!' => 'No hay nada nuevo que leer, ¡disfrute de sus artículos favoritos!', @@ -62,8 +63,7 @@ return array( 'Do not fetch the content of articles' => 'No extraer el contenido de los artículos', 'Remove automatically read items' => 'Borrar automáticamente los ítems leídos', 'Never' => 'Nunca', - 'After %d day' => 'Después de %d día', - 'After %d days' => 'Después de %d días', + 'After %d day' => array('Después de %d día', 'Después de %d días'), 'unread' => 'no leídos', 'Unread' => 'No leídos', 'bookmark' => 'añadir a marcadores', @@ -147,17 +147,11 @@ return array( 'Show help' => 'Mostrar la ayuda', 'Close help' => 'Cerrar la ayuda', // '%d second ago' => '', - // '%d seconds ago' => '', // '%d minute ago' => '', - // '%d minutes ago' => '', // '%d hour ago' => '', - // '%d hours ago' => '', // '%d day ago' => '', - // '%d days ago' => '', // '%d week ago' => '', - // '%d weeks ago' => '', // '%d month ago' => '', - // '%d months ago' => '', // 'Timezone' => '', // 'Update all subscriptions' => '', // 'Auto-Update URL' => '', diff --git a/locales/fr_FR/translations.php b/locales/fr_FR/translations.php index cf85347..e792e5e 100644 --- a/locales/fr_FR/translations.php +++ b/locales/fr_FR/translations.php @@ -1,6 +1,7 @@ function($n) { return ($n != 1); }, 'attachment' => 'pièce jointe', 'When there is nothing to read, redirect me to this page' => 'Quand il n\'y a rien à lire, redirigez moi vers cette page', 'There is nothing new to read, enjoy your favorites articles!' => 'Il n\'y a rien de nouveau à lire, relisez vos articles favoris !', @@ -62,8 +63,7 @@ return array( 'Do not fetch the content of articles' => 'Ne pas récupérer le contenu des articles', 'Remove automatically read items' => 'Supprimer automatiquement les éléments lus', 'Never' => 'Jamais', - 'After %d day' => 'Après %d jour', - 'After %d days' => 'Après %d jours', + 'After %d day' => array('Après %d jour', 'Après %d jours'), 'unread' => 'non lus', 'Unread' => 'Non lus', 'bookmark' => 'ajouter aux favoris', @@ -146,18 +146,12 @@ return array( 'Nothing to read, do you want to %supdate your subscriptions%s?' => 'Il n\'y a rien à lire, voulez-vous %smettre à jour vos abonnements%s ?', 'Show help' => 'Afficher l\'aide', 'Close help' => 'Fermer l\'aide', - '%d second ago' => 'Il y a %d seconde', - '%d seconds ago' => 'Il y a %d secondes', - '%d minute ago' => 'Il y a %d minute', - '%d minutes ago' => 'Il y a %d minutes', - '%d hour ago' => 'Il y a %d heure', - '%d hours ago' => 'Il y a %d heures', - '%d day ago' => 'Il y a %d jour', - '%d days ago' => 'Il y a %d jours', - '%d week ago' => 'Il y a %d semaine', - '%d weeks ago' => 'Il y a %d semaines', + '%d second ago' => array('Il y a %d seconde', 'Il y a %d secondes'), + '%d minute ago' => array('Il y a %d minute', 'Il y a %d minutes'), + '%d hour ago' => array('Il y a %d heure', 'Il y a %d heures'), + '%d day ago' => array('Il y a %d jour', 'Il y a %d jours'), + '%d week ago' => array('Il y a %d semaine', 'Il y a %d semaines'), '%d month ago' => 'Il y a %d mois', - '%d months ago' => 'Il y a %d mois', 'Timezone' => 'Fuseau horaire', 'Update all subscriptions' => 'Mettre à jour tous les abonnements', 'Auto-Update URL' => 'URL de mise à jour automatique', diff --git a/locales/it_IT/translations.php b/locales/it_IT/translations.php index 690c59a..cb69a02 100644 --- a/locales/it_IT/translations.php +++ b/locales/it_IT/translations.php @@ -1,6 +1,7 @@ function($n) { return ($n != 1); }, // 'attachment' => '', // 'When there is nothing to read, redirect me to this page' => '', // 'There is nothing new to read, enjoy your favorites articles!' => '', @@ -62,8 +63,7 @@ return array( 'Do not fetch the content of articles' => 'Non scaricare il contenuto degli articoli', 'Remove automatically read items' => 'Cancella automaticamente articoli già letti', 'Never' => 'Mai', - 'After %d day' => 'Dopo %d giorno', - 'After %d days' => 'Dopo %d giorni', + 'After %d day' => array('Dopo %d giorno', 'Dopo %d giorni'), 'unread' => 'non letti', 'Unread' => 'Non letti', 'bookmark' => 'bookmark', @@ -147,17 +147,11 @@ return array( 'Show help' => 'Mostra guida', 'Close help' => 'Chiudi guida', // '%d second ago' => '', - // '%d seconds ago' => '', // '%d minute ago' => '', - // '%d minutes ago' => '', // '%d hour ago' => '', - // '%d hours ago' => '', // '%d day ago' => '', - // '%d days ago' => '', // '%d week ago' => '', - // '%d weeks ago' => '', // '%d month ago' => '', - // '%d months ago' => '', // 'Timezone' => '', // 'Update all subscriptions' => '', // 'Auto-Update URL' => '', diff --git a/locales/pt_BR/translations.php b/locales/pt_BR/translations.php index 229ec57..05af6a5 100644 --- a/locales/pt_BR/translations.php +++ b/locales/pt_BR/translations.php @@ -1,6 +1,7 @@ function($n) { return ($n > 1); }, 'attachment' => 'anexo', 'When there is nothing to read, redirect me to this page' => 'Quando não houver nada para ler, me redirecione para esta página', 'There is nothing new to read, enjoy your favorites articles!' => 'Não há nada de novo para ler, desfrute de seus artigos favoritos!', @@ -62,8 +63,7 @@ return array( 'Do not fetch the content of articles' => 'Não buscar o conteúdo de artigos', 'Remove automatically read items' => 'Remover automaticamente itens lidos', 'Never' => 'Nunca', - 'After %d day' => 'Depois de %d dia', - 'After %d days' => 'Depois de %d dias', + 'After %d day' => array('Depois de %d dia', 'Depois de %d dias'), 'unread' => 'não lido', 'Unread' => 'Não lido', 'bookmark' => 'bookmark', @@ -146,18 +146,12 @@ return array( 'Nothing to read, do you want to %supdate your subscriptions%s?' => 'Nada para ler, você quer %satualizar suas assinaturas%s?', 'Show help' => 'Abrir ajuda', 'Close help' => 'Fechar ajuda', - '%d second ago' => '%d segundo atrás', - '%d seconds ago' => '%d segundos atrás', - '%d minute ago' => '%d minuto atrás', - '%d minutes ago' => '%d minutos atrás', - '%d hour ago' => '%d hora atrás', - '%d hours ago' => '%d horas atrás', - '%d day ago' => '%d dia atrás', - '%d days ago' => '%d dias atrás', - '%d week ago' => '%d semana atrás', - '%d weeks ago' => '%d semanas atrás', - '%d month ago' => '%d mês atrás', - '%d months ago' => '%d meses atrás', + '%d second ago' => array('%d segundo atrás', '%d segundos atrás'), + '%d minute ago' => array('%d minuto atrás', '%d minutos atrás'), + '%d hour ago' => array('%d hora atrás', '%d horas atrás'), + '%d day ago' => array('%d dia atrás', '%d dias atrás'), + '%d week ago' => array('%d semana atrás', '%d semanas atrás'), + '%d month ago' => array('%d mês atrás', '%d meses atrás'), 'Timezone' => 'Fuso horário', 'Update all subscriptions' => 'Atualizar todas as assinaturas', 'Auto-Update URL' => 'URL de atualização automática', diff --git a/locales/zh_CN/translations.php b/locales/zh_CN/translations.php index c6c004d..b8bfd62 100644 --- a/locales/zh_CN/translations.php +++ b/locales/zh_CN/translations.php @@ -1,6 +1,7 @@ function($n) { return 0; }, // 'attachment' => '', // 'When there is nothing to read, redirect me to this page' => '', // 'There is nothing new to read, enjoy your favorites articles!' => '', @@ -63,7 +64,6 @@ return array( 'Remove automatically read items' => '自动移除已读条目', 'Never' => '从不', 'After %d day' => '%d 天之后', - 'After %d days' => '%d 天之后', 'unread' => '未读', 'Unread' => '未读', 'bookmark' => '收藏', @@ -147,17 +147,11 @@ return array( 'Show help' => '显示帮助', 'Close help' => '关闭帮助', // '%d second ago' => '', - // '%d seconds ago' => '', // '%d minute ago' => '', - // '%d minutes ago' => '', // '%d hour ago' => '', - // '%d hours ago' => '', // '%d day ago' => '', - // '%d days ago' => '', // '%d week ago' => '', - // '%d weeks ago' => '', // '%d month ago' => '', - // '%d months ago' => '', // 'Timezone' => '', // 'Update all subscriptions' => '', // 'Auto-Update URL' => '', diff --git a/models/config.php b/models/config.php index 002c4d6..357e82e 100644 --- a/models/config.php +++ b/models/config.php @@ -142,9 +142,9 @@ function get_autoflush_read_options() '0' => t('Never'), '-1' => t('Immediately'), '1' => t('After %d day', 1), - '5' => t('After %d days', 5), - '15' => t('After %d days', 15), - '30' => t('After %d days', 30) + '5' => t('After %d day', 5), + '15' => t('After %d day', 15), + '30' => t('After %d day', 30) ); } @@ -153,10 +153,10 @@ function get_autoflush_unread_options() { return array( '0' => t('Never'), - '15' => t('After %d days', 15), - '30' => t('After %d days', 30), - '45' => t('After %d days', 45), - '60' => t('After %d days', 60), + '15' => t('After %d day', 15), + '30' => t('After %d day', 30), + '45' => t('After %d day', 45), + '60' => t('After %d day', 60), ); } diff --git a/scripts/sync-locales.php b/scripts/sync-locales.php index 2ed2df3..87ea804 100755 --- a/scripts/sync-locales.php +++ b/scripts/sync-locales.php @@ -10,17 +10,32 @@ function update_missing_locales(array $reference, $outdated_file) { $outdated = include $outdated_file; - $output = ' $value) { + foreach (array_keys($reference) as $key) { + $outputKey = str_replace("'", "\'", $key); + $outputValue = " // '".$outputKey."' => ''"; if (isset($outdated[$key])) { - $output .= " '".str_replace("'", "\'", $key)."' => '".str_replace("'", "\'", $outdated[$key])."',\n"; - } - else { - $output .= " // '".str_replace("'", "\'", $key)."' => '',\n"; + if ($key === 'plural') { + $outputValue = $outputKey."' => ".getFunctionCode($outdated[$key]); + } + elseif (is_array($outdated[$key])) { + foreach($outdated[$key] as &$value) { + $value = str_replace("'", "\'", $value); + } + + $outputValue = $outputKey."' => array('".join("', '", $outdated[$key])."')"; + } + else { + $outputValue = $outputKey."' => '".str_replace("'", "\'", $outdated[$key])."'"; + } + + $outputValue = " '".$outputValue; } + + $output .= $outputValue.",\n"; } $output .= ");\n"; @@ -30,7 +45,7 @@ function update_missing_locales(array $reference, $outdated_file) foreach (new DirectoryIterator('locales') as $fileInfo) { - if (! $fileInfo->isDot() && $fileInfo->isDir() && $fileInfo->getFilename() !== $reference_lang) { + if (! $fileInfo->isDot() && $fileInfo->isDir() && $fileInfo->getFilename() !== $reference_lang && $fileInfo->getFilename() !== 'en_US') { $filename = 'locales/'.$fileInfo->getFilename().'/translations.php'; @@ -39,3 +54,23 @@ foreach (new DirectoryIterator('locales') as $fileInfo) { file_put_contents($filename, update_missing_locales($reference, $filename)); } } + +function getFunctionCode($name) +{ + $reflector = new ReflectionFunction($name); + + $file = new SplFileObject($reflector->getFileName()); + $file->seek($reflector->getStartLine()-1); + + $sourcecode = ''; + while ($file->key() < $reflector->getEndLine()) + { + $sourcecode .= $file->current(); + $file->next(); + } + + $begin = strpos($sourcecode, 'function'); + $end = strrpos($sourcecode, '}'); + + return substr($sourcecode, $begin, $end - $begin + 1); +} \ No newline at end of file From d2598bac969fc521d801f7b85eb6ffbf0feff557 Mon Sep 17 00:00:00 2001 From: Mathias Kresin Date: Sat, 31 Jan 2015 08:15:27 +0100 Subject: [PATCH 2/2] improvements for multiple plural support for translations - calculate the plural number only if the term has multiple plurals - only numbers can be converted to absolute values --- lib/Translator.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/Translator.php b/lib/Translator.php index 393bf78..29f8aee 100644 --- a/lib/Translator.php +++ b/lib/Translator.php @@ -87,17 +87,16 @@ namespace Translator { $translation = $default; $plural = 0; - foreach ($values as $value) { - $value = abs($value); - - if (is_numeric($value)) { - $plural = (int)$locales['plural']($value); - break; - } - } - if (isset($locales[$identifier])) { if (is_array($locales[$identifier])) { + foreach ($values as $value) { + if (is_numeric($value)) { + $value = abs($value); + $plural = (int)$locales['plural']($value); + break; + } + } + $translation = $locales[$identifier][$plural]; } else {