@@ -5,16 +5,41 @@ const {symlink, lstatSync, readdirSync} = require('fs');
5
5
6
6
const SYMLINKED_TRANSLATIONS_PATH = path . resolve ( __dirname , 'translations' ) ;
7
7
const DOWNLOADED_TRANSLATIONS_PATH = path . resolve ( __dirname , '__translations' ) ;
8
- const DOWNLOADED_TRANSLATIONS_DOCS_PATH = path . resolve (
8
+
9
+ // Path to the "docs" folder within the downloaded Crowdin translations bundle.
10
+ const downloadedDocsPath = path . resolve (
9
11
__dirname ,
10
12
'__translations' ,
13
+ config . downloadedRootDirectory ,
11
14
'docs' ,
12
15
) ;
13
16
14
- function main ( ) {
15
- const crowdin = new Crowdin ( { apiKey : config . key , endpointUrl : config . url } ) ;
16
- process . chdir ( SYMLINKED_TRANSLATIONS_PATH ) ;
17
+ // Sanity check (local) Crowdin config file for expected values.
18
+ const validateCrowdinConfig = ( ) => {
19
+ const errors = [ ] ;
20
+ if ( ! config . key ) {
21
+ errors . push ( 'key: No process.env.CROWDIN_API_KEY value defined.' ) ;
22
+ }
23
+ if ( ! Number . isInteger ( config . threshold ) ) {
24
+ errors . push ( `threshold: Invalid translation threshold defined.` ) ;
25
+ }
26
+ if ( ! config . downloadedRootDirectory ) {
27
+ errors . push ( 'downloadedRootDirectory: No root directory defined for the downloaded translations bundle.' ) ;
28
+ }
29
+ if ( ! config . url ) {
30
+ errors . push ( 'url: No Crowdin project URL defined.' ) ;
31
+ }
32
+ if ( errors . length > 0 ) {
33
+ console . error ( 'Invalid Crowdin config values for:\n• ' + errors . join ( '\n• ' ) ) ;
34
+ throw Error ( 'Invalid Crowdin config' ) ;
35
+ }
36
+ } ;
17
37
38
+ // Download Crowdin translations (into DOWNLOADED_TRANSLATIONS_PATH),
39
+ // Filter languages that have been sufficiently translated (based on config.threshold),
40
+ // And setup symlinks for them (in SYMLINKED_TRANSLATIONS_PATH) for Gatsby to read.
41
+ const downloadAndSymlink = ( ) => {
42
+ const crowdin = new Crowdin ( { apiKey : config . key , endpointUrl : config . url } ) ;
18
43
crowdin
19
44
// .export() // Not sure if this should be called in the script since it could be very slow
20
45
// .then(() => crowdin.downloadToPath(DOWNLOADED_TRANSLATIONS_PATH))
@@ -23,56 +48,56 @@ function main() {
23
48
. then ( locales => {
24
49
const usableLocales = locales
25
50
. filter (
26
- locale => locale . translated_progress > config . translation_threshold ,
51
+ locale => locale . translated_progress > config . threshold ,
27
52
)
28
53
. map ( local => local . code ) ;
29
54
30
- const localeDirectories = getDirectories (
31
- DOWNLOADED_TRANSLATIONS_DOCS_PATH ,
32
- ) ;
33
-
55
+ const localeDirectories = getLanguageDirectories ( downloadedDocsPath ) ;
34
56
const localeToFolderMap = createLocaleToFolderMap ( localeDirectories ) ;
35
57
36
58
usableLocales . forEach ( locale => {
37
59
createSymLink ( localeToFolderMap . get ( locale ) ) ;
38
60
} ) ;
39
61
} ) ;
40
- }
62
+
63
+ } ;
41
64
42
65
// Creates a relative symlink from a downloaded translation in the current working directory
43
66
// Note that the current working directory of this node process should be where the symlink is created
44
67
// or else the relative paths would be incorrect
45
- function createSymLink ( folder ) {
46
- symlink ( `../__translations/docs/${ folder } ` , folder , err => {
68
+ const createSymLink = ( folder ) => {
69
+ const from = path . resolve ( downloadedDocsPath , folder ) ;
70
+ const to = path . resolve ( SYMLINKED_TRANSLATIONS_PATH , folder ) ;
71
+ symlink ( from , to , err => {
47
72
if ( ! err ) {
48
- console . log ( `Created symlink for ${ folder } .` ) ;
49
73
return ;
50
74
}
51
75
52
76
if ( err . code === 'EEXIST' ) {
53
- console . log (
54
- `Skipped creating symlink for ${ folder } . A symlink already exists.` ,
55
- ) ;
77
+ // eslint-disable-next-line no-console
78
+ console . info ( `Symlink already exists for ${ folder } ` ) ;
56
79
} else {
57
80
console . error ( err ) ;
58
81
process . exit ( 1 ) ;
59
82
}
60
83
} ) ;
61
- }
84
+ } ;
62
85
63
- // When we run getTranslationStatus(), it gives us 2-ALPHA locale codes unless necessary
64
- // However, the folder structure of downloaded translations always has 4-ALPHA locale codes
65
- // This function creates a map from a locale code to its corresponding folder name
66
- function createLocaleToFolderMap ( directories ) {
67
- const twoAlphaLocale = locale => locale . substring ( 0 , 2 ) ;
86
+ // Crowdin.getTranslationStatus() provides ISO 639-1 (e.g. "fr" for French) or 639-3 (e.g. "fil" for Filipino) language codes,
87
+ // But the folder structure of downloaded translations uses locale codes (e.g. "fr-FR" for French, "fil-PH" for the Philippines).
88
+ // This function creates a map between language and locale code.
89
+ const createLocaleToFolderMap = ( directories ) => {
90
+ const localeToLanguageCode = locale => locale . includes ( '-' ) ? locale . substr ( 0 , locale . indexOf ( '-' ) ) : locale ;
68
91
const localeToFolders = new Map ( ) ;
69
92
const localeToFolder = new Map ( ) ;
70
93
71
94
for ( let locale of directories ) {
95
+ const languageCode = localeToLanguageCode ( locale ) ;
96
+
72
97
localeToFolders . set (
73
- twoAlphaLocale ( locale ) ,
74
- localeToFolders . has ( twoAlphaLocale ( locale ) )
75
- ? localeToFolders . get ( twoAlphaLocale ( locale ) ) . concat ( locale )
98
+ languageCode ,
99
+ localeToFolders . has ( languageCode )
100
+ ? localeToFolders . get ( languageCode ) . concat ( locale )
76
101
: [ locale ] ,
77
102
) ;
78
103
}
@@ -88,13 +113,14 @@ function createLocaleToFolderMap(directories) {
88
113
} ) ;
89
114
90
115
return localeToFolder ;
91
- }
116
+ } ;
92
117
93
- function getDirectories ( source ) {
94
- return readdirSync ( source ) . filter (
118
+ // Parse downloaded translation folder to determine which langauges it contains.
119
+ const getLanguageDirectories = source =>
120
+ readdirSync ( source ) . filter (
95
121
name =>
96
122
lstatSync ( path . join ( source , name ) ) . isDirectory ( ) && name !== '_data' ,
97
123
) ;
98
- }
99
124
100
- main ( ) ;
125
+ validateCrowdinConfig ( config ) ;
126
+ downloadAndSymlink ( ) ;
0 commit comments