add multiple plural support for translations

fixes #242
This commit is contained in:
Mathias Kresin 2015-01-30 19:45:23 +01:00
parent 60d125a05e
commit ddcae31d48
13 changed files with 120 additions and 105 deletions

View File

@ -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');

View File

@ -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('#(?<!%)((?:%%)*)%e#', '\1%#d', $format);
$format = preg_replace('#(?<!%)((?:%%)*)%k#', '\1%#H', $format);
}
return strftime($format, (int) $timestamp);
}
function get($identifier, $default = '')
function get($identifier, $default = '', $values = array())
{
$locales = container();
$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])) {
return $locales[$identifier];
if (is_array($locales[$identifier])) {
$translation = $locales[$identifier][$plural];
}
else {
$translation = $locales[$identifier];
}
}
else {
return $default;
}
return $translation;
}

View File

@ -135,22 +135,22 @@ function relative_time($timestamp, $fallback_date_format = '%e %B %Y %k:%M')
if ($diff < 0) return \dt($fallback_date_format, $timestamp);
if ($diff < 60) return \t('%d second'.($diff > 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);
}

View File

@ -1,6 +1,7 @@
<?php
return array(
'plural' => 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' => '',

View File

@ -1,6 +1,7 @@
<?php
return array(
'plural' => 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',

View File

@ -0,0 +1,12 @@
<?php
return array(
'plural' => 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'),
);

View File

@ -1,6 +1,7 @@
<?php
return array(
'plural' => 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' => '',

View File

@ -1,6 +1,7 @@
<?php
return array(
'plural' => 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',

View File

@ -1,6 +1,7 @@
<?php
return array(
'plural' => 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' => '',

View File

@ -1,6 +1,7 @@
<?php
return array(
'plural' => 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',

View File

@ -1,6 +1,7 @@
<?php
return array(
'plural' => 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' => '',

View File

@ -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),
);
}

View File

@ -10,17 +10,32 @@ function update_missing_locales(array $reference, $outdated_file)
{
$outdated = include $outdated_file;
$output = '<?php'.PHP_EOL.PHP_EOL;
$output .= 'return array('.PHP_EOL;
$output = "<?php\n\n";
$output .= "return array(\n";
foreach ($reference as $key => $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);
}