implementing a plural translation solution, currently only the JS part
This commit is contained in:
parent
eee7b0144a
commit
c83ba8256f
4 changed files with 130 additions and 101 deletions
43
i18n/de.json
43
i18n/de.json
|
@ -57,36 +57,27 @@
|
||||||
"Diskussion",
|
"Diskussion",
|
||||||
"Toggle navigation":
|
"Toggle navigation":
|
||||||
"Navigation umschalten",
|
"Navigation umschalten",
|
||||||
"5 minutes":
|
"%d seconds": ["%d Sekunde", "%d Sekunden"],
|
||||||
"5 Minuten",
|
"%d minutes": ["%d Minute", "%d Minuten"],
|
||||||
"10 minutes":
|
"%d hours": ["%d Stunde", "%d Stunden"],
|
||||||
"10 Minuten",
|
"%d days": ["%d Tag", "%d Tage"],
|
||||||
"1 hour":
|
"%d weeks": ["%d Woche", "%d Wochen"],
|
||||||
"1 Stunde",
|
"%d months": ["%d Monat", "%d Monate"],
|
||||||
"1 day":
|
"%d years": ["%d Jahr", "%d Jahre"],
|
||||||
"1 Tag",
|
|
||||||
"1 week":
|
|
||||||
"1 Woche",
|
|
||||||
"1 month":
|
|
||||||
"1 Monat",
|
|
||||||
"1 year":
|
|
||||||
"1 Jahr",
|
|
||||||
"Never":
|
"Never":
|
||||||
"Nie",
|
"Nie",
|
||||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||||
"Hinweis: Dies ist ein Versuchsdienst. Daten können jederzeit gelöscht werden. Kätzchen werden sterben wenn Du diesen Dienst missbrauchst.",
|
"Hinweis: Dies ist ein Versuchsdienst. Daten können jederzeit gelöscht werden. Kätzchen werden sterben wenn Du diesen Dienst missbrauchst.",
|
||||||
"This document will expire in %s.":
|
"This document will expire in %d seconds.":
|
||||||
"Dieses Dokument läuft in %s ab.",
|
["Dieses Dokument läuft in einer Sekunde ab.", "Dieses Dokument läuft in %d Sekunden ab."],
|
||||||
"%d second": "einer Sekunde",
|
"This document will expire in %d minutes.":
|
||||||
"%d seconds": "%d Sekunden",
|
["Dieses Dokument läuft in einer Minute ab.", "Dieses Dokument läuft in %d Minuten ab."],
|
||||||
"%d minute": "einer Minute",
|
"This document will expire in %d hours.":
|
||||||
"%d minutes": "%d Minuten",
|
["Dieses Dokument läuft in einer Stunde ab.", "Dieses Dokument läuft in %d Stunden ab."],
|
||||||
"%d hour": "einer Stunde",
|
"This document will expire in %d days.":
|
||||||
"%d hours": "%d Stunden",
|
["Dieses Dokument läuft in einem Tag ab.", "Dieses Dokument läuft in %d Tagen ab."],
|
||||||
"%d day": "einem Tag",
|
"This document will expire in %d months.":
|
||||||
"%d days": "%d Tagen",
|
["Dieses Dokument läuft in einem Monat ab.", "Dieses Dokument läuft in %d Monaten ab."],
|
||||||
"%d month": "einem Monat",
|
|
||||||
"%d months": "%d Monaten",
|
|
||||||
"Please enter the password for this paste:":
|
"Please enter the password for this paste:":
|
||||||
"Bitte gib das Passwort für diesen Text ein:",
|
"Bitte gib das Passwort für diesen Text ein:",
|
||||||
"Could not decrypt data (Wrong key?)":
|
"Could not decrypt data (Wrong key?)":
|
||||||
|
|
43
i18n/fr.json
43
i18n/fr.json
|
@ -57,36 +57,27 @@
|
||||||
"Discussion",
|
"Discussion",
|
||||||
"Toggle navigation":
|
"Toggle navigation":
|
||||||
"Basculer la navigation",
|
"Basculer la navigation",
|
||||||
"5 minutes":
|
"%d seconds": ["%d second", "%d seconds"],
|
||||||
"5 minutes",
|
"%d minutes": ["%d minute", "%d minutes"],
|
||||||
"10 minutes":
|
"%d hours": ["%d heure", "%d heures"],
|
||||||
"10 minutes",
|
"%d days": ["%d jour", "%d jours"],
|
||||||
"1 hour":
|
"%d weeks": ["%d semaine", "%d semaines"],
|
||||||
"1 heure",
|
"%d months": ["%d mois", "%d mois"],
|
||||||
"1 day":
|
"%d years": ["%d an", "%d ans"],
|
||||||
"1 jour",
|
|
||||||
"1 week":
|
|
||||||
"1 semaine",
|
|
||||||
"1 month":
|
|
||||||
"1 mois",
|
|
||||||
"1 year":
|
|
||||||
"1 an",
|
|
||||||
"Never":
|
"Never":
|
||||||
"Jamais",
|
"Jamais",
|
||||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||||
"Note : Ceci est un service de test : les données peuvent être supprimées à tout moment. Des chatons mourront si vous utilisez ce service de manière abusive.",
|
"Note : Ceci est un service de test : les données peuvent être supprimées à tout moment. Des chatons mourront si vous utilisez ce service de manière abusive.",
|
||||||
"This document will expire in %s.":
|
"This document will expire in %d seconds.":
|
||||||
"This document will expire in %s.",
|
["This document will expire in %d second.", "This document will expire in %d seconds."],
|
||||||
"%d second": "%d second",
|
"This document will expire in %d minutes.":
|
||||||
"%d seconds": "%d seconds",
|
["This document will expire in %d minute.", "This document will expire in %d minutes."],
|
||||||
"%d minute": "%d minute",
|
"This document will expire in %d hours.":
|
||||||
"%d minutes": "%d minutes",
|
["This document will expire in %d hour.", "This document will expire in %d hours."],
|
||||||
"%d hour": "%d hour",
|
"This document will expire in %d days.":
|
||||||
"%d hours": "%d hours",
|
["This document will expire in %d day.", "This document will expire in %d days."],
|
||||||
"%d day": "%d day",
|
"This document will expire in %d months.":
|
||||||
"%d days": "%d days",
|
["This document will expire in %d month.", "This document will expire in %d months."],
|
||||||
"%d month": "%d month",
|
|
||||||
"%d months": "%d months",
|
|
||||||
"Please enter the password for this paste:":
|
"Please enter the password for this paste:":
|
||||||
"Please enter the password for this paste:",
|
"Please enter the password for this paste:",
|
||||||
"Could not decrypt data (Wrong key?)":
|
"Could not decrypt data (Wrong key?)":
|
||||||
|
|
43
i18n/pl.json
43
i18n/pl.json
|
@ -57,36 +57,27 @@
|
||||||
"Dyskusja",
|
"Dyskusja",
|
||||||
"Toggle navigation":
|
"Toggle navigation":
|
||||||
"Przełącz nawigację",
|
"Przełącz nawigację",
|
||||||
"5 minutes":
|
"%d seconds": ["%d second", "%d second", "%d second"],
|
||||||
"5 minut",
|
"%d minutes": ["%d minut", "%d minut", "%d minut"],
|
||||||
"10 minutes":
|
"%d hours": ["%d godzina", "%d godzina", "%d godzina"],
|
||||||
"10 minut",
|
"%d days": ["%d dzień", "%d dzień", "%d dzień"],
|
||||||
"1 hour":
|
"%d weeks": ["%d tydzień", "%d tydzień", "%d tydzień"],
|
||||||
"1 godzina",
|
"%d months": ["%d miesiąc", "%d miesiąc", "%d miesiąc"],
|
||||||
"1 day":
|
"%d years": ["%d rok", "%d rok", "%d rok"],
|
||||||
"1 dzień",
|
|
||||||
"1 week":
|
|
||||||
"1 tydzień",
|
|
||||||
"1 month":
|
|
||||||
"1 miesiąc",
|
|
||||||
"1 year":
|
|
||||||
"1 rok",
|
|
||||||
"Never":
|
"Never":
|
||||||
"Nigdy",
|
"Nigdy",
|
||||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||||
"Notka: To jest usługa testowa. Dane mogą zostać usunięte w dowolnym momencie. Kociątka umrą, jeśli nadużyjesz tej usługi.",
|
"Notka: To jest usługa testowa. Dane mogą zostać usunięte w dowolnym momencie. Kociątka umrą, jeśli nadużyjesz tej usługi.",
|
||||||
"This document will expire in %s.":
|
"This document will expire in %d seconds.":
|
||||||
"This document will expire in %s.",
|
["This document will expire in %d second.", "This document will expire in %d seconds."],
|
||||||
"%d second": "%d second",
|
"This document will expire in %d minutes.":
|
||||||
"%d seconds": "%d seconds",
|
["This document will expire in %d minute.", "This document will expire in %d minutes."],
|
||||||
"%d minute": "%d minute",
|
"This document will expire in %d hours.":
|
||||||
"%d minutes": "%d minutes",
|
["This document will expire in %d hour.", "This document will expire in %d hours."],
|
||||||
"%d hour": "%d hour",
|
"This document will expire in %d days.":
|
||||||
"%d hours": "%d hours",
|
["This document will expire in %d day.", "This document will expire in %d days."],
|
||||||
"%d day": "%d day",
|
"This document will expire in %d months.":
|
||||||
"%d days": "%d days",
|
["This document will expire in %d month.", "This document will expire in %d months."],
|
||||||
"%d month": "%d month",
|
|
||||||
"%d months": "%d months",
|
|
||||||
"Please enter the password for this paste:":
|
"Please enter the password for this paste:":
|
||||||
"Please enter the password for this paste:",
|
"Please enter the password for this paste:",
|
||||||
"Could not decrypt data (Wrong key?)":
|
"Could not decrypt data (Wrong key?)":
|
||||||
|
|
102
js/zerobin.js
102
js/zerobin.js
|
@ -20,41 +20,36 @@ $(function() {
|
||||||
*/
|
*/
|
||||||
var helper = {
|
var helper = {
|
||||||
/**
|
/**
|
||||||
* Converts a duration (in seconds) into human readable format.
|
* Converts a duration (in seconds) into human friendly approximation.
|
||||||
*
|
*
|
||||||
* @param int seconds
|
* @param int seconds
|
||||||
* @return string
|
* @return array
|
||||||
*/
|
*/
|
||||||
secondsToHuman: function(seconds)
|
secondsToHuman: function(seconds)
|
||||||
{
|
{
|
||||||
if (seconds < 60)
|
if (seconds < 60)
|
||||||
{
|
{
|
||||||
var v = Math.floor(seconds),
|
var v = Math.floor(seconds);
|
||||||
format = '%d second' + ((v > 1) ? 's' : '');
|
return [v, 'second'];
|
||||||
return i18n._(format, v);
|
|
||||||
}
|
}
|
||||||
if (seconds < 60 * 60)
|
if (seconds < 60 * 60)
|
||||||
{
|
{
|
||||||
var v = Math.floor(seconds / 60),
|
var v = Math.floor(seconds / 60);
|
||||||
format = '%d minute' + ((v > 1) ? 's' : '');
|
return [v, 'minute'];
|
||||||
return i18n._(format, v);
|
|
||||||
}
|
}
|
||||||
if (seconds < 60 * 60 * 24)
|
if (seconds < 60 * 60 * 24)
|
||||||
{
|
{
|
||||||
var v = Math.floor(seconds / (60 * 60)),
|
var v = Math.floor(seconds / (60 * 60));
|
||||||
format = '%d hour' + ((v > 1) ? 's' : '');
|
return [v, 'hour'];
|
||||||
return i18n._(format, v);
|
|
||||||
}
|
}
|
||||||
// If less than 2 months, display in days:
|
// If less than 2 months, display in days:
|
||||||
if (seconds < 60 * 60 * 24 * 60)
|
if (seconds < 60 * 60 * 24 * 60)
|
||||||
{
|
{
|
||||||
var v = Math.floor(seconds / (60 * 60 * 24)),
|
var v = Math.floor(seconds / (60 * 60 * 24));
|
||||||
format = '%d day' + ((v > 1) ? 's' : '');
|
return [v, 'day'];
|
||||||
return i18n._(format, v);
|
|
||||||
}
|
}
|
||||||
var v = Math.floor(seconds / (60 * 60 * 24 * 30)),
|
var v = Math.floor(seconds / (60 * 60 * 24 * 30));
|
||||||
format = '%d month' + ((v > 1) ? 's' : '');
|
return [v, 'month'];
|
||||||
return i18n._(format, v);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -258,7 +253,29 @@ $(function() {
|
||||||
* internationalization methods
|
* internationalization methods
|
||||||
*/
|
*/
|
||||||
var i18n = {
|
var i18n = {
|
||||||
supportedLanguages: ['de', 'fr', 'pl'], // and the built in 'en'
|
/**
|
||||||
|
* supported languages, minus the built in 'en'
|
||||||
|
*/
|
||||||
|
supportedLanguages: ['de', 'fr', 'pl'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* per language functions to use to determine the plural form
|
||||||
|
* From: http://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html
|
||||||
|
*
|
||||||
|
* @param int number
|
||||||
|
* @return int array key
|
||||||
|
*/
|
||||||
|
pluralRules: {
|
||||||
|
de: function(n) {
|
||||||
|
return (n != 1 ? 1 : 0);
|
||||||
|
},
|
||||||
|
fr: function(n) {
|
||||||
|
return (n > 1 ? 1 : 0);
|
||||||
|
},
|
||||||
|
pl: function(n) {
|
||||||
|
return (n == 1 ? 0 : n%10 >= 2 && n %10 <=4 && (n%100 < 10 || n%100 >= 20) ? 1 : 2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* translate a string, alias for translate()
|
* translate a string, alias for translate()
|
||||||
|
@ -281,30 +298,64 @@ $(function() {
|
||||||
*/
|
*/
|
||||||
translate: function()
|
translate: function()
|
||||||
{
|
{
|
||||||
var args = arguments;
|
var args = arguments, messageId, usesPlurals;
|
||||||
if (typeof arguments[0] == 'object') args = arguments[0];
|
if (typeof arguments[0] == 'object') args = arguments[0];
|
||||||
var messageId = args[0];
|
if (usesPlurals = $.isArray(args[0]))
|
||||||
|
{
|
||||||
|
// use the first plural form as messageId, otherwise the singular
|
||||||
|
messageId = (args[0].length > 1 ? args[0][1] : args[0][0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
messageId = args[0];
|
||||||
|
}
|
||||||
if (messageId.length == 0) return messageId;
|
if (messageId.length == 0) return messageId;
|
||||||
if (!this.translations.hasOwnProperty(messageId))
|
if (!this.translations.hasOwnProperty(messageId))
|
||||||
{
|
{
|
||||||
console.log('Missing translation for: ' + messageId);
|
console.log('Missing translation for: ' + messageId);
|
||||||
this.translations[messageId] = messageId;
|
this.translations[messageId] = args[0];
|
||||||
|
}
|
||||||
|
if (usesPlurals && $.isArray(this.translations[messageId]))
|
||||||
|
{
|
||||||
|
var n = parseInt(args[1] || 1),
|
||||||
|
key = this.pluralRules[this.language](n),
|
||||||
|
maxKey = this.translations[messageId].length - 1;
|
||||||
|
if (key > maxKey) key = maxKey;
|
||||||
|
args[0] = this.translations[messageId][key];
|
||||||
|
args[1] = n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
args[0] = this.translations[messageId];
|
||||||
}
|
}
|
||||||
args[0] = this.translations[messageId];
|
|
||||||
return helper.sprintf(args);
|
return helper.sprintf(args);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load translations into cache, then execute callback function
|
||||||
|
*
|
||||||
|
* @param function callback
|
||||||
|
*/
|
||||||
loadTranslations: function(callback)
|
loadTranslations: function(callback)
|
||||||
{
|
{
|
||||||
var language = (navigator.language || navigator.userLanguage).substring(0, 2);
|
var language = (navigator.language || navigator.userLanguage).substring(0, 2);
|
||||||
// note that 'en' is built in, so no translation is necessary
|
// note that 'en' is built in, so no translation is necessary
|
||||||
if (this.supportedLanguages.indexOf(language) == -1) return;
|
if (this.supportedLanguages.indexOf(language) == -1) return;
|
||||||
$.getJSON('i18n/' + language + '.json', function(data) {
|
$.getJSON('i18n/' + language + '.json', function(data) {
|
||||||
|
i18n.language = language;
|
||||||
i18n.translations = data;
|
i18n.translations = data;
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* built in language
|
||||||
|
*/
|
||||||
|
language: 'en',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* translation cache
|
||||||
|
*/
|
||||||
translations: {}
|
translations: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,8 +546,13 @@ $(function() {
|
||||||
// Display paste expiration.
|
// Display paste expiration.
|
||||||
if (comments[0].meta.expire_date)
|
if (comments[0].meta.expire_date)
|
||||||
{
|
{
|
||||||
|
var expiration = helper.secondsToHuman(comments[0].meta.remaining_time),
|
||||||
|
expirationLabel = [
|
||||||
|
'This document will expire in %d ' + expiration[1] + '.',
|
||||||
|
'This document will expire in %d ' + expiration[1] + 's.'
|
||||||
|
];
|
||||||
this.remainingTime.removeClass('foryoureyesonly')
|
this.remainingTime.removeClass('foryoureyesonly')
|
||||||
.text(i18n._('This document will expire in %s.', helper.secondsToHuman(comments[0].meta.remaining_time)))
|
.text(i18n._(expirationLabel, expiration[0]))
|
||||||
.removeClass('hidden');
|
.removeClass('hidden');
|
||||||
}
|
}
|
||||||
if (comments[0].meta.burnafterreading)
|
if (comments[0].meta.burnafterreading)
|
||||||
|
|
Loading…
Reference in a new issue