diff --git a/gulp/res/js/forms.js b/gulp/res/js/forms.js index fc2578e5..d86b0b05 100644 --- a/gulp/res/js/forms.js +++ b/gulp/res/js/forms.js @@ -1,4 +1,4 @@ -/* globals modal Tegaki grecaptcha hcaptcha captchaController appendLocalStorageArray socket isThread setLocalStorage forceUpdate captchaController uploaditem */ +/* globals __n modal Tegaki grecaptcha hcaptcha captchaController appendLocalStorageArray socket isThread setLocalStorage forceUpdate captchaController uploaditem */ async function videoThumbnail(file) { return new Promise((resolve, reject) => { const hiddenVideo = document.createElement('video'); @@ -517,9 +517,9 @@ class postFormHandler { if (this.files && this.files.length === 0) { this.fileUploadList.textContent = ''; this.fileUploadList.style.display = 'none'; - this.fileLabelText.nodeValue = `Select/Drop/Paste file${this.multipleFiles ? 's' : ''}`; + this.fileLabelText.nodeValue = __n('Select/Drop/Paste files', this.multipleFiles ? 2 : 1); } else { - this.fileLabelText.nodeValue = `${this.files.length} file${this.files.length > 1 ? 's' : ''} selected`; + this.fileLabelText.nodeValue = __n('%s files selected', this.files.length); } this.fileInput.value = null; } diff --git a/gulp/res/js/i18n.js b/gulp/res/js/i18n.js index baf2faf5..6125a90f 100644 --- a/gulp/res/js/i18n.js +++ b/gulp/res/js/i18n.js @@ -1,6 +1,18 @@ /* eslint-disable no-unused-vars */ /* globals LANG */ + +const pluralMap = { + 1: 'one', + // two, three, few, many, ... +}; + +//simple translation const __ = (key) => { - //TODO: we'll see if this needs to be more advanced in future return LANG[key]; }; + +//plurals+replace %s with count +const __n = (key, count) => { + const pluralKey = pluralMap[count] || 'other'; + return LANG[key][pluralKey].replace('%s', count); +}; diff --git a/gulpfile.js b/gulpfile.js index a20ccdf5..7d6d0e27 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -466,6 +466,7 @@ const extraLocals = ${JSON.stringify({ meta: config.get.meta, reverseImageLinksU `; fs.writeFileSync('gulp/res/js/locals.js', locals); + del([ 'static/js/lang/' ]), fs.mkdirSync(`${paths.scripts.dest}lang/`); Object.entries(i18n.getCatalog()) .forEach(entry => { diff --git a/locales/en.json b/locales/en.json index df6dad6c..9bef07e2 100644 --- a/locales/en.json +++ b/locales/en.json @@ -21,13 +21,24 @@ "Email": "Email", "Subject": "Subject", "Message": "Message", - "Files": "Files", - "File": "File", - "Max": "Max", + "Files": { + "one": "File", + "other": "Files" + }, + "Max %s files": { + "one": "Max %s file", + "other": "Max %s files" + }, "total": "total", "Password": "Password", - "Select/Drop/Paste file": "Select/Drop/Paste file", - "Select/Drop/Paste files": "Select/Drop/Paste files", + "Select/Drop/Paste files": { + "one": "Select/Drop/Paste file", + "other": "Select/Drop/Paste files" + }, + "%s files selected": { + "one": "%s file selected", + "other": "%s files selected" + }, "Tegaki": "Tegaki", "Replayable?": "Replayable?", "Draw": "Draw", diff --git a/locales/pt.json b/locales/pt.json index a327b08d..b85e6077 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -21,13 +21,24 @@ "Email": "Opção", "Subject": "Assunto", "Message": "Mensagem", - "Files": "Ficheiros", - "Files": "Ficheiro", - "Max": "Máx", + "Files": { + "one": "Ficheiro", + "other": "Ficheiros" + }, + "Max %s files": { + "one": "Máx %s", + "other": "Máx %s" + }, "total": "total", "Password": "Password", - "Select/Drop/Paste file": "Seleciona/Arrasta/Cola ficheiro", - "Select/Drop/Paste files": "Seleciona/Arrasta/Cola ficheiros", + "Select/Drop/Paste files": { + "one": "Seleciona/Arrasta/Cola ficheiro", + "other": "Seleciona/Arrasta/Cola ficheiros" + }, + "%s files selected": { + "one": "%s ficheiro selecionado", + "other": "%s ficheiros selecionados" + }, "Tegaki": "Tegaki", "Replayable?": "Replay?", "Draw": "Desenhar", diff --git a/views/includes/postform.pug b/views/includes/postform.pug index eb2b9301..33b26cf8 100644 --- a/views/includes/postform.pug +++ b/views/includes/postform.pug @@ -44,13 +44,13 @@ section.form-wrapper.flex-center - const maxFiles = board.settings.maxFiles; section.row .label - span #{__(`File${maxFiles > 1 ? 's' : ''}`)} + span #{__n('Files', maxFiles)} if fileRequired span.required * | | if maxFiles > 1 - small #{__('Max')} #{maxFiles} + small #{__n('Max %s files', maxFiles)} small #{postFilesSize} #{__('total')} span.col +filelabel('file', maxFiles) diff --git a/views/mixins/filelabel.pug b/views/mixins/filelabel.pug index 0630687a..59bbd309 100644 --- a/views/mixins/filelabel.pug +++ b/views/mixins/filelabel.pug @@ -1,3 +1,3 @@ mixin filelabel(id, max) label.jsonly.postform-style.filelabel(for=id) - | #{__(`Select/Drop/Paste file${max > 1 ? 's' : ''}`)} + | #{__n(`Select/Drop/Paste files`, max)}