forked from cybrespace/mastodon
		
	Streamline javascript translation by improving translationRunner (#2808)
* 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.js
This commit is contained in:
		
							parent
							
								
									ddc34feb58
								
							
						
					
					
						commit
						cf0b753209
					
				
					 8 changed files with 101 additions and 41 deletions
				
			
		
							
								
								
									
										5
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -46,5 +46,10 @@ redis
 | 
			
		|||
/public/packs
 | 
			
		||||
/node_modules
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Ignore npm debug log
 | 
			
		||||
npm-debug.log
 | 
			
		||||
 | 
			
		||||
# Ignore Docker option files
 | 
			
		||||
docker-compose.override.yml
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,8 @@
 | 
			
		|||
  "account.edit_profile": "עריכת פרופיל",
 | 
			
		||||
  "account.follow": "מעקב",
 | 
			
		||||
  "account.followers": "עוקבים",
 | 
			
		||||
  "account.follows_you": "במעקב אחריך",
 | 
			
		||||
  "account.follows": "נעקבים",
 | 
			
		||||
  "account.follows_you": "במעקב אחריך",
 | 
			
		||||
  "account.mention": "אזכור של @{name}",
 | 
			
		||||
  "account.mute": "להשתיק את @{name}",
 | 
			
		||||
  "account.posts": "הודעות",
 | 
			
		||||
| 
						 | 
				
			
			@ -53,8 +53,9 @@
 | 
			
		|||
  "emoji_button.travel": "טיולים ואתרים",
 | 
			
		||||
  "empty_column.community": "טור הסביבה ריק. יש לפרסם משהו כדי שדברים יתרחילו להתגלגל!",
 | 
			
		||||
  "empty_column.hashtag": "אין כלום בהאשתג הזה עדיין.",
 | 
			
		||||
  "empty_column.home.public_timeline": "בפרהסיה",
 | 
			
		||||
  "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.public": "אין פה כלום! כדי למלא את הטור הזה אפשר לכתוב משהו, או להתחיל לעקוב אחרי אנשים מקהילות אחרות.",
 | 
			
		||||
  "follow_request.authorize": "קבלה",
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +85,6 @@
 | 
			
		|||
  "navigation_bar.public_timeline": "בפרהסיה",
 | 
			
		||||
  "notification.favourite": "חצרוצך חובב על ידי {name}",
 | 
			
		||||
  "notification.follow": "{name} במעקב אחרייך",
 | 
			
		||||
  "notification.mention": "אוזכרת ע\"י {name}",
 | 
			
		||||
  "notification.reblog": "חצרוצך הודהד על ידי {name}",
 | 
			
		||||
  "notifications.clear": "הסרת התראות",
 | 
			
		||||
  "notifications.clear_confirmation": "להסיר את כל ההתראות? בטוח?",
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +131,6 @@
 | 
			
		|||
  "report.submit": "שליחה",
 | 
			
		||||
  "report.target": "דיווח",
 | 
			
		||||
  "search.placeholder": "חיפוש",
 | 
			
		||||
  "search.status_by": "הודעה מאת {name}",
 | 
			
		||||
  "search_results.total": "{count, number} {count, plural, one {תוצאה} other {תוצאות}}",
 | 
			
		||||
  "status.cannot_reblog": "לא ניתן להדהד הודעה זו",
 | 
			
		||||
  "status.delete": "מחיקה",
 | 
			
		||||
| 
						 | 
				
			
			@ -145,8 +144,8 @@
 | 
			
		|||
  "status.reply": "תגובה",
 | 
			
		||||
  "status.replyAll": "תגובה לכולם",
 | 
			
		||||
  "status.report": "דיווח על @{name}",
 | 
			
		||||
  "status.sensitive_warning": "תוכן רגיש",
 | 
			
		||||
  "status.sensitive_toggle": "לחצו כדי לראות",
 | 
			
		||||
  "status.sensitive_warning": "תוכן רגיש",
 | 
			
		||||
  "status.show_less": "הראה פחות",
 | 
			
		||||
  "status.show_more": "הראה יותר",
 | 
			
		||||
  "tabs_bar.compose": "חיבור",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,8 +53,9 @@
 | 
			
		|||
  "emoji_button.travel": "Podróże i miejsca",
 | 
			
		||||
  "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.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.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.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić.",
 | 
			
		||||
  "follow_request.authorize": "Autoryzuj",
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +85,6 @@
 | 
			
		|||
  "navigation_bar.public_timeline": "Oś czasu federacji",
 | 
			
		||||
  "notification.favourite": "{name} dodał twój status do ulubionych",
 | 
			
		||||
  "notification.follow": "{name} zaczął cię obserwować",
 | 
			
		||||
  "notification.mention": "{name} wspomniał o tobie",
 | 
			
		||||
  "notification.reblog": "{name} podbił twój status",
 | 
			
		||||
  "notifications.clear": "Wyczyść powiadomienia",
 | 
			
		||||
  "notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?",
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +131,6 @@
 | 
			
		|||
  "report.submit": "Wyślij",
 | 
			
		||||
  "report.target": "Zgłaszanie",
 | 
			
		||||
  "search.placeholder": "Szukaj",
 | 
			
		||||
  "search.status_by": "Status od {name}",
 | 
			
		||||
  "search_results.total": "{count, number} {count, plural, one {wynik} more {wyniki}}",
 | 
			
		||||
  "status.cannot_reblog": "Ten post nie może zostać podbity",
 | 
			
		||||
  "status.delete": "Usuń",
 | 
			
		||||
| 
						 | 
				
			
			@ -161,5 +160,5 @@
 | 
			
		|||
  "video_player.expand": "Przełącz wideo",
 | 
			
		||||
  "video_player.toggle_sound": "Przełącz dźwięk",
 | 
			
		||||
  "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"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								app/javascript/mastodon/locales/whitelist_he.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/javascript/mastodon/locales/whitelist_he.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
[
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										2
									
								
								app/javascript/mastodon/locales/whitelist_pl.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/javascript/mastodon/locales/whitelist_pl.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
[
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			@ -7,8 +7,8 @@ const { readFileSync } = require('fs')
 | 
			
		|||
 | 
			
		||||
const configPath = resolve('config', 'webpack')
 | 
			
		||||
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
 | 
			
		||||
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 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({
 | 
			
		||||
  messagesDirectory: 'build/messages',
 | 
			
		||||
  translationsDirectory: 'app/javascript/mastodon/locales/',
 | 
			
		||||
  translationsDirectory,
 | 
			
		||||
  detectDuplicateIds: false,
 | 
			
		||||
  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",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "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",
 | 
			
		||||
    "start": "babel-node ./streaming/index.js --presets es2015,stage-2",
 | 
			
		||||
    "storybook": "start-storybook -p 9001 -c storybook",
 | 
			
		||||
| 
						 | 
				
			
			@ -113,6 +115,7 @@
 | 
			
		|||
    "eslint-plugin-jsx-a11y": "^4.0.0",
 | 
			
		||||
    "eslint-plugin-react": "^6.10.3",
 | 
			
		||||
    "jsdom": "^9.11.0",
 | 
			
		||||
    "minimist": "^1.2.0",
 | 
			
		||||
    "mocha": "^3.2.0",
 | 
			
		||||
    "react-intl-translations-manager": "^5.0.0",
 | 
			
		||||
    "webpack-dev-server": "^2.4.5"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue