* package.json: Add "build:*" targets * Improve react-intl-translations-manager workflow. * Added "build:production" to build production bundle. * Added "build:development" to build development bundle. * Fix json translation files * Run `yarn manage:translations` to fix translation files. * Fix `pl.json` for syntax error. * translationRunner: auto detect existing languages * Auto detect existing rfc5646 language tag in *.json filenames in `app/javascript/mastodon/locale` folder. No need to manually define every new language in the languages array here. * translationRunner: add more functionality * Allow script user to specify language code to check. * Added available language check. * Added --force flag to force creation of unexists language. * Added --help flag and help messages. * gitignore: ignore npm-debug.log * Fix webpack error if NODE_ENV is not defined Default to use 'development' in config/webpack/configuration.jsmaster
@@ -46,5 +46,10 @@ redis | |||||
/public/packs | /public/packs | ||||
/node_modules | /node_modules | ||||
# Ignore npm debug log | |||||
npm-debug.log | |||||
# Ignore Docker option files | # Ignore Docker option files | ||||
docker-compose.override.yml | docker-compose.override.yml | ||||
@@ -4,8 +4,8 @@ | |||||
"account.edit_profile": "עריכת פרופיל", | "account.edit_profile": "עריכת פרופיל", | ||||
"account.follow": "מעקב", | "account.follow": "מעקב", | ||||
"account.followers": "עוקבים", | "account.followers": "עוקבים", | ||||
"account.follows_you": "במעקב אחריך", | |||||
"account.follows": "נעקבים", | "account.follows": "נעקבים", | ||||
"account.follows_you": "במעקב אחריך", | |||||
"account.mention": "אזכור של @{name}", | "account.mention": "אזכור של @{name}", | ||||
"account.mute": "להשתיק את @{name}", | "account.mute": "להשתיק את @{name}", | ||||
"account.posts": "הודעות", | "account.posts": "הודעות", | ||||
@@ -53,8 +53,9 @@ | |||||
"emoji_button.travel": "טיולים ואתרים", | "emoji_button.travel": "טיולים ואתרים", | ||||
"empty_column.community": "טור הסביבה ריק. יש לפרסם משהו כדי שדברים יתרחילו להתגלגל!", | "empty_column.community": "טור הסביבה ריק. יש לפרסם משהו כדי שדברים יתרחילו להתגלגל!", | ||||
"empty_column.hashtag": "אין כלום בהאשתג הזה עדיין.", | "empty_column.hashtag": "אין כלום בהאשתג הזה עדיין.", | ||||
"empty_column.home.public_timeline": "בפרהסיה", | |||||
"empty_column.home": "אף אחד לא במעקב עדיין. אפשר לבקר ב{public} או להשתמש בחיפוש כדי להתחיל ולהכיר חצוצרנים אחרים.", | "empty_column.home": "אף אחד לא במעקב עדיין. אפשר לבקר ב{public} או להשתמש בחיפוש כדי להתחיל ולהכיר חצוצרנים אחרים.", | ||||
"empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.", | |||||
"empty_column.home.public_timeline": "בפרהסיה", | |||||
"empty_column.notifications": "אין התראות עדיין. יאללה, הגיע הזמן להתחיל להתערבב!", | "empty_column.notifications": "אין התראות עדיין. יאללה, הגיע הזמן להתחיל להתערבב!", | ||||
"empty_column.public": "אין פה כלום! כדי למלא את הטור הזה אפשר לכתוב משהו, או להתחיל לעקוב אחרי אנשים מקהילות אחרות.", | "empty_column.public": "אין פה כלום! כדי למלא את הטור הזה אפשר לכתוב משהו, או להתחיל לעקוב אחרי אנשים מקהילות אחרות.", | ||||
"follow_request.authorize": "קבלה", | "follow_request.authorize": "קבלה", | ||||
@@ -84,7 +85,6 @@ | |||||
"navigation_bar.public_timeline": "בפרהסיה", | "navigation_bar.public_timeline": "בפרהסיה", | ||||
"notification.favourite": "חצרוצך חובב על ידי {name}", | "notification.favourite": "חצרוצך חובב על ידי {name}", | ||||
"notification.follow": "{name} במעקב אחרייך", | "notification.follow": "{name} במעקב אחרייך", | ||||
"notification.mention": "אוזכרת ע\"י {name}", | |||||
"notification.reblog": "חצרוצך הודהד על ידי {name}", | "notification.reblog": "חצרוצך הודהד על ידי {name}", | ||||
"notifications.clear": "הסרת התראות", | "notifications.clear": "הסרת התראות", | ||||
"notifications.clear_confirmation": "להסיר את כל ההתראות? בטוח?", | "notifications.clear_confirmation": "להסיר את כל ההתראות? בטוח?", | ||||
@@ -131,7 +131,6 @@ | |||||
"report.submit": "שליחה", | "report.submit": "שליחה", | ||||
"report.target": "דיווח", | "report.target": "דיווח", | ||||
"search.placeholder": "חיפוש", | "search.placeholder": "חיפוש", | ||||
"search.status_by": "הודעה מאת {name}", | |||||
"search_results.total": "{count, number} {count, plural, one {תוצאה} other {תוצאות}}", | "search_results.total": "{count, number} {count, plural, one {תוצאה} other {תוצאות}}", | ||||
"status.cannot_reblog": "לא ניתן להדהד הודעה זו", | "status.cannot_reblog": "לא ניתן להדהד הודעה זו", | ||||
"status.delete": "מחיקה", | "status.delete": "מחיקה", | ||||
@@ -145,8 +144,8 @@ | |||||
"status.reply": "תגובה", | "status.reply": "תגובה", | ||||
"status.replyAll": "תגובה לכולם", | "status.replyAll": "תגובה לכולם", | ||||
"status.report": "דיווח על @{name}", | "status.report": "דיווח על @{name}", | ||||
"status.sensitive_warning": "תוכן רגיש", | |||||
"status.sensitive_toggle": "לחצו כדי לראות", | "status.sensitive_toggle": "לחצו כדי לראות", | ||||
"status.sensitive_warning": "תוכן רגיש", | |||||
"status.show_less": "הראה פחות", | "status.show_less": "הראה פחות", | ||||
"status.show_more": "הראה יותר", | "status.show_more": "הראה יותר", | ||||
"tabs_bar.compose": "חיבור", | "tabs_bar.compose": "חיבור", | ||||
@@ -162,4 +161,4 @@ | |||||
"video_player.toggle_sound": "הפעלת\\ביטול שמע", | "video_player.toggle_sound": "הפעלת\\ביטול שמע", | ||||
"video_player.toggle_visible": "הפעלת\\ביטול תצוגה", | "video_player.toggle_visible": "הפעלת\\ביטול תצוגה", | ||||
"video_player.video_error": "לא ניתן לנגן וידאו" | "video_player.video_error": "לא ניתן לנגן וידאו" | ||||
} | |||||
} |
@@ -53,8 +53,9 @@ | |||||
"emoji_button.travel": "Podróże i miejsca", | "emoji_button.travel": "Podróże i miejsca", | ||||
"empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby odbić piłeczkę!", | "empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby odbić piłeczkę!", | ||||
"empty_column.hashtag": "Nie ma postów oznaczonych tym hashtagiem. Możesz napisać pierwszy!", | "empty_column.hashtag": "Nie ma postów oznaczonych tym hashtagiem. Możesz napisać pierwszy!", | ||||
"empty_column.home.public_timeline": "publiczna oś czasu", | |||||
"empty_column.home": "Nie obserwujesz nikogo. Odwiedź publiczną oś czasu lub użyj wyszukiwarki, aby znaleźć ciekawych ludzi.", | "empty_column.home": "Nie obserwujesz nikogo. Odwiedź publiczną oś czasu lub użyj wyszukiwarki, aby znaleźć ciekawych ludzi.", | ||||
"empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.", | |||||
"empty_column.home.public_timeline": "publiczna oś czasu", | |||||
"empty_column.notifications": "Nie masz żadnych powiadomień. Rozpocznij interakcje z innymi użytkownikami.", | "empty_column.notifications": "Nie masz żadnych powiadomień. Rozpocznij interakcje z innymi użytkownikami.", | ||||
"empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić.", | "empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić.", | ||||
"follow_request.authorize": "Autoryzuj", | "follow_request.authorize": "Autoryzuj", | ||||
@@ -84,7 +85,6 @@ | |||||
"navigation_bar.public_timeline": "Oś czasu federacji", | "navigation_bar.public_timeline": "Oś czasu federacji", | ||||
"notification.favourite": "{name} dodał twój status do ulubionych", | "notification.favourite": "{name} dodał twój status do ulubionych", | ||||
"notification.follow": "{name} zaczął cię obserwować", | "notification.follow": "{name} zaczął cię obserwować", | ||||
"notification.mention": "{name} wspomniał o tobie", | |||||
"notification.reblog": "{name} podbił twój status", | "notification.reblog": "{name} podbił twój status", | ||||
"notifications.clear": "Wyczyść powiadomienia", | "notifications.clear": "Wyczyść powiadomienia", | ||||
"notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?", | "notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?", | ||||
@@ -131,7 +131,6 @@ | |||||
"report.submit": "Wyślij", | "report.submit": "Wyślij", | ||||
"report.target": "Zgłaszanie", | "report.target": "Zgłaszanie", | ||||
"search.placeholder": "Szukaj", | "search.placeholder": "Szukaj", | ||||
"search.status_by": "Status od {name}", | |||||
"search_results.total": "{count, number} {count, plural, one {wynik} more {wyniki}}", | "search_results.total": "{count, number} {count, plural, one {wynik} more {wyniki}}", | ||||
"status.cannot_reblog": "Ten post nie może zostać podbity", | "status.cannot_reblog": "Ten post nie może zostać podbity", | ||||
"status.delete": "Usuń", | "status.delete": "Usuń", | ||||
@@ -161,5 +160,5 @@ | |||||
"video_player.expand": "Przełącz wideo", | "video_player.expand": "Przełącz wideo", | ||||
"video_player.toggle_sound": "Przełącz dźwięk", | "video_player.toggle_sound": "Przełącz dźwięk", | ||||
"video_player.toggle_visible": "Przełącz widoczność", | "video_player.toggle_visible": "Przełącz widoczność", | ||||
"video_player.video_error": "Nie można odtworzyć pliku wideo", | |||||
}; | |||||
"video_player.video_error": "Nie można odtworzyć pliku wideo" | |||||
} |
@@ -0,0 +1,2 @@ | |||||
[ | |||||
] |
@@ -0,0 +1,2 @@ | |||||
[ | |||||
] |
@@ -7,8 +7,8 @@ const { readFileSync } = require('fs') | |||||
const configPath = resolve('config', 'webpack') | const configPath = resolve('config', 'webpack') | ||||
const loadersDir = join(__dirname, 'loaders') | const loadersDir = join(__dirname, 'loaders') | ||||
const paths = safeLoad(readFileSync(join(configPath, 'paths.yml'), 'utf8'))[env.NODE_ENV] | |||||
const devServer = safeLoad(readFileSync(join(configPath, 'development.server.yml'), 'utf8'))[env.NODE_ENV] | |||||
const paths = safeLoad(readFileSync(join(configPath, 'paths.yml'), 'utf8'))[env.NODE_ENV || 'development'] | |||||
const devServer = safeLoad(readFileSync(join(configPath, 'development.server.yml'), 'utf8'))[env.NODE_ENV || 'development'] | |||||
// Compute public path based on environment and CDN_HOST in production | // Compute public path based on environment and CDN_HOST in production | ||||
const ifHasCDN = env.CDN_HOST !== undefined && env.NODE_ENV === 'production' | const ifHasCDN = env.CDN_HOST !== undefined && env.NODE_ENV === 'production' | ||||
@@ -1,34 +1,84 @@ | |||||
/*eslint no-console: "off"*/ | |||||
const manageTranslations = require('react-intl-translations-manager').default; | const manageTranslations = require('react-intl-translations-manager').default; | ||||
const argv = require('minimist')(process.argv.slice(2)); | |||||
const fs = require('fs'); | |||||
const translationsDirectory = 'app/javascript/mastodon/locales'; | |||||
const localeFn = /^([a-z]{2,3}(|\-[A-Z]+))\.json$/; | |||||
const reRFC5646 = /^[a-z]{2,3}(|\-[A-Z]+)$/; | |||||
const availableLanguages = fs.readdirSync(`${process.cwd()}/${translationsDirectory}`).reduce((acc, fn) => { | |||||
if (fn.match(localeFn)) { | |||||
acc.push(fn.replace(localeFn, '$1')); | |||||
} | |||||
return acc; | |||||
}, []); | |||||
// print help message | |||||
if (argv.help !== undefined) { | |||||
console.log( | |||||
`Usage: yarn manage:translations -- [OPTIONS] [LANGUAGES] | |||||
Manage javascript translation files in mastodon. Generates and update | |||||
translations in translationsDirectory: ${translationsDirectory} | |||||
OPTIONS | |||||
--help show this message | |||||
--force force using the provided languages. create files if not exists. | |||||
default: false | |||||
LANGUAGES | |||||
The RFC5646 language tag for the language you want to test or fix. If you want | |||||
to input multiple languages, separate them with space. | |||||
Available languages: | |||||
${availableLanguages} | |||||
`); | |||||
process.exit(0); | |||||
} | |||||
// determine the languages list | |||||
const languages = (argv._.length === 0) ? availableLanguages : argv._; | |||||
// check if the languages provided are RFC5626 compliant | |||||
(function() { | |||||
let invalidLanguages = languages.reduce((acc, language) => { | |||||
if (!language.match(reRFC5646)) { | |||||
acc.push(language); | |||||
} | |||||
return acc; | |||||
}, []); | |||||
if (invalidLanguages.length > 0) { | |||||
console.log(`Error:`); | |||||
for (let language of invalidLanguages) { | |||||
console.error(`* Not RFC5626 name: ${language}`); | |||||
} | |||||
console.log(`\nUse yarn "manage:translations -- --help" for usage information\n`); | |||||
process.exit(1); | |||||
} | |||||
})(); | |||||
// make sure the language exists. Unless force to create locale file. | |||||
if (argv.force !== true) { | |||||
let invalidLanguages = languages.reduce((acc, language) => { | |||||
if (availableLanguages.indexOf(language) < 0) { | |||||
acc.push(language); | |||||
} | |||||
return acc; | |||||
}, []); | |||||
if (invalidLanguages.length > 0) { | |||||
console.log(`Error:`); | |||||
for (let language of invalidLanguages) { | |||||
console.error(`* Language not available: ${language}`); | |||||
} | |||||
console.log(`\nIf you want to force creating the language(s) above, please add the --force option.\n`); | |||||
process.exit(1); | |||||
} | |||||
} | |||||
manageTranslations({ | manageTranslations({ | ||||
messagesDirectory: 'build/messages', | messagesDirectory: 'build/messages', | ||||
translationsDirectory: 'app/javascript/mastodon/locales/', | |||||
translationsDirectory, | |||||
detectDuplicateIds: false, | detectDuplicateIds: false, | ||||
singleMessagesFile: true, | singleMessagesFile: true, | ||||
languages: [ | |||||
'ar', | |||||
'en', | |||||
'de', | |||||
'es', | |||||
'fa', | |||||
'hr', | |||||
'hu', | |||||
'io', | |||||
'it', | |||||
'fr', | |||||
'nl', | |||||
'no', | |||||
'oc', | |||||
'pt', | |||||
'pt-BR', | |||||
'uk', | |||||
'fi', | |||||
'eo', | |||||
'ru', | |||||
'ja', | |||||
'zh-HK', | |||||
'zh-CN', | |||||
'bg', | |||||
'id', | |||||
], | |||||
}) | |||||
languages, | |||||
}); |
@@ -3,6 +3,8 @@ | |||||
"license": "AGPL-3.0", | "license": "AGPL-3.0", | ||||
"scripts": { | "scripts": { | ||||
"postversion": "git push --tags", | "postversion": "git push --tags", | ||||
"build:development": "NODE_ENV=development yarn webpack -- --config config/webpack/development.js", | |||||
"build:production": "NODE_ENV=production yarn webpack -- --config config/webpack/production.js", | |||||
"manage:translations": "node ./config/webpack/translationRunner.js", | "manage:translations": "node ./config/webpack/translationRunner.js", | ||||
"start": "babel-node ./streaming/index.js --presets es2015,stage-2", | "start": "babel-node ./streaming/index.js --presets es2015,stage-2", | ||||
"storybook": "start-storybook -p 9001 -c storybook", | "storybook": "start-storybook -p 9001 -c storybook", | ||||
@@ -113,6 +115,7 @@ | |||||
"eslint-plugin-jsx-a11y": "^4.0.0", | "eslint-plugin-jsx-a11y": "^4.0.0", | ||||
"eslint-plugin-react": "^6.10.3", | "eslint-plugin-react": "^6.10.3", | ||||
"jsdom": "^9.11.0", | "jsdom": "^9.11.0", | ||||
"minimist": "^1.2.0", | |||||
"mocha": "^3.2.0", | "mocha": "^3.2.0", | ||||
"react-intl-translations-manager": "^5.0.0", | "react-intl-translations-manager": "^5.0.0", | ||||
"webpack-dev-server": "^2.4.5" | "webpack-dev-server": "^2.4.5" | ||||