Skip to content

Commit

Permalink
i18n: Add full i18n support
Browse files Browse the repository at this point in the history
This adds i18n support for the app, being
rendered in client-side so that translations
can be loaded dynamically. Implemented language
fallbacks for non-existing translations, plurals
and dynamic placeholders for strings.

Fixes #38
  • Loading branch information
mooncos committed Dec 14, 2017
1 parent 1827a74 commit 148d879
Show file tree
Hide file tree
Showing 20 changed files with 2,523 additions and 21 deletions.
4 changes: 2 additions & 2 deletions .coafile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[all]
files = **.js, **.json, **.css, **.yml, **.html, .eslintrc
ignore = node_modules/**, out/**, package-lock.json
ignore = node_modules/**, out/**, package-lock.json, static/js/lib/**
max_line_length = 80
use_spaces = True

Expand All @@ -9,7 +9,7 @@ bears = SpaceConsistencyBear
default_actions = *: ApplyPatchAction

[all.linelength]
ignore += **.html
ignore += **.html, static/js/i18n/**.json
bears = LineLengthBear

[all.links]
Expand Down
50 changes: 39 additions & 11 deletions static/js/app.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-env jquery */

document.getElementById('ago').textContent = `(${timeDifference(
new Date().getTime(),
new Date(document.getElementById('time').dataset.time).getTime()
Expand All @@ -13,17 +15,44 @@ function timeDifference(current, previous) {
const elapsed = current - previous

if (elapsed < msPerMinute) {
return Math.round(elapsed / 1000) + ' seconds ago'
return $.i18n('seconds-ago', Math.round(elapsed / 1000))
} else if (elapsed < msPerHour) {
return $.i18n('minutes-ago', Math.round(elapsed / msPerMinute))
} else if (elapsed < msPerDay) {
return $.i18n('hours-ago', Math.round(elapsed / msPerHour))
} else if (elapsed < msPerMonth) {
return $.i18n('days-ago', Math.round(elapsed / msPerDay))
} else if (elapsed < msPerYear) {
return $.i18n('months-ago', Math.round(elapsed / msPerMonth))
} else {
return $.i18n('years-ago', Math.round(elapsed / msPerYear))
}
}

// this is needed for time expression translation.
// will be removed when we find a way
// to correctly strip the "ago" segment of a translation
function timeDifferenceFuture(current, previous) {
const msPerMinute = 60 * 1000
const msPerHour = msPerMinute * 60
const msPerDay = msPerHour * 24
const msPerMonth = msPerDay * 30
const msPerYear = msPerDay * 365

const elapsed = current - previous

if (elapsed < msPerMinute) {
return $.i18n('seconds', Math.round(elapsed / 1000))
} else if (elapsed < msPerHour) {
return Math.round(elapsed / msPerMinute) + ' minutes ago'
return $.i18n('minutes', Math.round(elapsed / msPerMinute))
} else if (elapsed < msPerDay) {
return Math.round(elapsed / msPerHour) + ' hours ago'
return $.i18n('hours', Math.round(elapsed / msPerHour))
} else if (elapsed < msPerMonth) {
return 'approximately ' + Math.round(elapsed / msPerDay) + ' days ago'
return $.i18n('days', Math.round(elapsed / msPerDay))
} else if (elapsed < msPerYear) {
return 'approximately ' + Math.round(elapsed / msPerMonth) + ' months ago'
return $.i18n('months', Math.round(elapsed / msPerMonth))
} else {
return 'approximately ' + Math.round(elapsed / msPerYear) + ' years ago'
return $.i18n('years', Math.round(elapsed / msPerYear))
}
}

Expand Down Expand Up @@ -51,10 +80,9 @@ function gciProgress() {
'style',
'width:' + percentagePassed + '%;height: 8px;border-radius: 100px;'
)
return (
Math.round(percentagePassed) +
'% passed, ' +
timeDifference(noClaims, current).slice(0, -4) +
' before task claiming ends'
return $.i18n(
'passed',
Math.round(percentagePassed),
timeDifferenceFuture(noClaims, current)
)
}
12 changes: 12 additions & 0 deletions static/js/global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* eslint-env jquery */

var current_locale = $.i18n().locale

$.i18n()
.load('./static/js/i18n', current_locale)
.done(function() {
$(document).ready(function() {
console.log('i18n:' + current_locale + ' locale loaded')
$('body').i18n()
})
})
21 changes: 21 additions & 0 deletions static/js/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"page-title": "Google Code-in 2017 Current Leaders",
"last-updated": "Last updated",
"order-info": "The leading participants for each organization (and their GitHub accounts, if applicable) are listed randomly.",
"tasks-completed": "Tasks Completed",
"footer-text": "Google Code-in and the Google Code-in logo are trademarks of Google Inc.",
"orgs-no-listed": "Organization(s) with no listed leaders",
"passed": "$1% passed, approximately $2 before task claiming ends",
"seconds-ago": "$1 {{PLURAL:$1|second|seconds}} ago",
"minutes-ago": "$1 {{PLURAL:$1|minute|minutes}} ago",
"hours-ago": "$1 {{PLURAL:$1|hour|hours}} ago",
"days-ago": "$1 {{PLURAL:$1|day|days}} ago",
"months-ago": "$1 {{PLURAL:$1|month|months}} ago",
"years-ago": "$1 {{PLURAL:$1|year|years}} ago",
"seconds": "$1 {{PLURAL:$1|second|seconds}}",
"minutes": "$1 {{PLURAL:$1|minute|minutes}}",
"hours": "$1 {{PLURAL:$1|hour|hours}}",
"days": "$1 {{PLURAL:$1|day|days}}",
"months": "$1 {{PLURAL:$1|month|months}}",
"years": "$1 {{PLURAL:$1|year|years}}"
}
21 changes: 21 additions & 0 deletions static/js/i18n/es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"page-title": "Líderes actuales de Google Code-in 2017",
"last-updated": "Última actualización",
"order-info": "Los participantes líderes de cada organización (y sus respectivas cuentas de GitHub) están listados de forma aleatoria.",
"tasks-completed": "Tareas completadas",
"footer-text": "Google Code-in y su logotipo son marcas registradas de Google Inc.",
"orgs-no-listed": "Organizacion(es) sin listado de líderes",
"passed": "$1% completado, aproximadamente $2 hasta que termine el periodo de tareas",
"seconds-ago": "hace $1 {{PLURAL:$1|segundo|segundos}}",
"minutes-ago": "hace $1 {{PLURAL:$1|minuto|minutos}}",
"hours-ago": "hace $1 {{PLURAL:$1|hora|horas}}",
"days-ago": "hace $1 {{PLURAL:$1|día|días}}",
"months-ago": "hace $1 {{PLURAL:$1|mes|meses}}",
"years-ago": "hace $1 {{PLURAL:$1|año|años}}",
"seconds": "$1 {{PLURAL:$1|segundo|segundos}}",
"minutes": "$1 {{PLURAL:$1|minuto|minutos}}",
"hours": "$1 {{PLURAL:$1|hora|horas}}",
"days": "$1 {{PLURAL:$1|día|días}}",
"months": "$1 {{PLURAL:$1|mes|meses}}",
"years": "$1 {{PLURAL:$1|año|años}}"
}
21 changes: 21 additions & 0 deletions static/js/i18n/hi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"page-title": "Google Code-in 2017 वर्तमान नेता",
"last-updated": "आखरी अपडेट",
"order-info": "प्रत्येक संगठन (और उनके GitHub खाते, यदि लागू हो) के लिए प्रमुख प्रतिभागी क्रमशः सूचीबद्ध होते हैं",
"tasks-completed": "पूरा कार्य",
"footer-text": "Google Code-in और इसके लोगो Google Inc. के ट्रेडमार्क हैं",
"orgs-no-listed": "जिन सूचीबद्ध नेताओं के साथ संगठन नहीं",
"passed": "$1% passed, approximately $2 before task claiming ends",
"seconds-ago": "$1 सेकंड पहले",
"minutes-ago": "$1 मिनट पहले",
"hours-ago": "$1 घंटे पहले",
"days-ago": "$1 दिन पहले",
"months-ago": "$1 महिनो पहले",
"years-ago": "$1 साल पहले",
"seconds": "$1 सेकंड",
"minutes": "$1 मिनट",
"hours": "$1 घंटे",
"days": "$1 दिन",
"months": "$1 महिनो",
"years": "$1 साल"
}
21 changes: 21 additions & 0 deletions static/js/i18n/id.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"page-title": "Google Code-in 2017 Pemimpin Saat Ini",
"last-updated": "Terakhir diperbarui",
"order-info": "Peserta utama untuk setiap organisasi (dan akun GitHub mereka, jika ada) terdaftar secara acak.",
"tasks-completed": "Tugas selesai",
"footer-text": "Google Code-in dan logonya adalah merek dagang terdaftar dari Google Inc.",
"orgs-no-listed": "Organisasi tanpa pemimpin yang terdaftar",
"passed": "$1% passed, approximately $2 before task claiming ends",
"seconds-ago": "$1 {{PLURAL:$1|second|seconds}} ago",
"minutes-ago": "$1 {{PLURAL:$1|minute|minutes}} ago",
"hours-ago": "$1 {{PLURAL:$1|hour|hours}} ago",
"days-ago": "$1 {{PLURAL:$1|day|days}} ago",
"months-ago": "$1 {{PLURAL:$1|month|months}} ago",
"years-ago": "$1 {{PLURAL:$1|year|years}} ago",
"seconds": "$1 {{PLURAL:$1|second|seconds}}",
"minutes": "$1 {{PLURAL:$1|minute|minutes}}",
"hours": "$1 {{PLURAL:$1|hour|hours}}",
"days": "$1 {{PLURAL:$1|day|days}}",
"months": "$1 {{PLURAL:$1|month|months}}",
"years": "$1 {{PLURAL:$1|year|years}}"
}
21 changes: 21 additions & 0 deletions static/js/i18n/ja.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"page-title": "Google Code-in 2017の現在のリーダー",
"last-updated": "最終更新",
"order-info": "組織化(そして、適用できるならば、彼らのGitHubは説明します)につき主要な参加者は、ランダムにリストされます",
"tasks-completed": "完了された仕事",
"footer-text": "Google Code-inとそのロゴは、Google社の登録商標です",
"orgs-no-listed": "リストされたリーダーのない組織",
"passed": "$1% passed, approximately $2 before task claiming ends",
"seconds-ago": "$1 {{PLURAL:$1|second|seconds}} ago",
"minutes-ago": "$1 {{PLURAL:$1|minute|minutes}} ago",
"hours-ago": "$1 {{PLURAL:$1|hour|hours}} ago",
"days-ago": "$1 {{PLURAL:$1|day|days}} ago",
"months-ago": "$1 {{PLURAL:$1|month|months}} ago",
"years-ago": "$1 {{PLURAL:$1|year|years}} ago",
"seconds": "$1 {{PLURAL:$1|second|seconds}}",
"minutes": "$1 {{PLURAL:$1|minute|minutes}}",
"hours": "$1 {{PLURAL:$1|hour|hours}}",
"days": "$1 {{PLURAL:$1|day|days}}",
"months": "$1 {{PLURAL:$1|month|months}}",
"years": "$1 {{PLURAL:$1|year|years}}"
}
21 changes: 21 additions & 0 deletions static/js/i18n/ru.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"page-title": "Google Code-in 2017 году нынешние лидеры",
"last-updated": "Последнее обновление",
"order-info": "Ведущие участники каждой организации (и их учетные записи GitHub, если применимо) перечислены случайным образом.",
"tasks-completed": "Задачи завершены",
"footer-text": "Google Code-in и его логотип являются товарными знаками Google Inc.",
"orgs-no-listed": "Организации без лидирующих лидеров",
"passed": "$1% passed, approximately $2 before task claiming ends",
"seconds-ago": "$1 {{PLURAL:$1|second|seconds}} ago",
"minutes-ago": "$1 {{PLURAL:$1|minute|minutes}} ago",
"hours-ago": "$1 {{PLURAL:$1|hour|hours}} ago",
"days-ago": "$1 {{PLURAL:$1|day|days}} ago",
"months-ago": "$1 {{PLURAL:$1|month|months}} ago",
"years-ago": "$1 {{PLURAL:$1|year|years}} ago",
"seconds": "$1 {{PLURAL:$1|second|seconds}}",
"minutes": "$1 {{PLURAL:$1|minute|minutes}}",
"hours": "$1 {{PLURAL:$1|hour|hours}}",
"days": "$1 {{PLURAL:$1|day|days}}",
"months": "$1 {{PLURAL:$1|month|months}}",
"years": "$1 {{PLURAL:$1|year|years}}"
}
Loading

0 comments on commit 148d879

Please sign in to comment.