1+ const { google } = require ( 'googleapis' ) ;
2+ const fs = require ( 'fs' ) ;
3+ const path = require ( 'path' ) ;
4+
5+ const parseLocalizationFiles = ( folderPath ) => {
6+ const files = fs . readdirSync ( folderPath ) . filter ( file => file . endsWith ( '.json' ) ) ;
7+
8+ if ( files . length === 0 ) {
9+ console . log ( `No localization files found in folder: ${ folderPath } ` ) ;
10+ return { languages : [ ] , translations : { } } ;
11+ }
12+
13+ const languages = [ ] ;
14+ const translations = { } ;
15+
16+ for ( const file of files ) {
17+ const lang = path . basename ( file , '.json' ) ; // Extract language code from file name
18+ languages . push ( lang ) ;
19+
20+ const jsonData = JSON . parse ( fs . readFileSync ( `${ folderPath } /${ file } ` , 'utf8' ) ) ;
21+ const texts = jsonData . texts || jsonData . Texts || { } ; // Use 'texts' or 'Texts' if they exist, otherwise default to {}
22+ for ( const [ key , value ] of Object . entries ( texts ) ) {
23+ if ( ! translations [ key ] ) translations [ key ] = { } ;
24+ if ( value ) { // Only add non-empty values
25+ translations [ key ] [ lang ] = value ;
26+ }
27+ }
28+ }
29+
30+ return { languages, translations } ;
31+ } ;
32+
33+ const processFolder = async ( folderPath , sheetName , sheets , existingSheetNames , spreadsheetId ) => {
34+ const { languages, translations } = parseLocalizationFiles ( folderPath ) ;
35+
36+ if ( languages . length === 0 ) {
37+ return ;
38+ }
39+
40+ // Prepare rows for Google Sheets
41+ const rows = [ [ 'Key' , ...languages ] ] ; // Header row
42+ for ( const [ key , values ] of Object . entries ( translations ) ) {
43+ const row = [ key ] ;
44+ for ( const lang of languages ) {
45+ row . push ( values [ lang ] || '' ) ; // Add translation or empty if missing
46+ }
47+ rows . push ( row ) ;
48+ }
49+
50+ // Create new sheet if it does not exist
51+ if ( ! existingSheetNames . includes ( sheetName ) ) {
52+ await sheets . spreadsheets . batchUpdate ( {
53+ spreadsheetId,
54+ resource : {
55+ requests : [
56+ {
57+ addSheet : {
58+ properties : {
59+ title : sheetName ,
60+ } ,
61+ } ,
62+ } ,
63+ ] ,
64+ } ,
65+ } ) ;
66+ }
67+
68+ // Push data to Google Sheets
69+ const range = `${ sheetName } !A1` ;
70+ await sheets . spreadsheets . values . update ( {
71+ spreadsheetId,
72+ range,
73+ valueInputOption : 'RAW' ,
74+ resource : { values : rows } ,
75+ } ) ;
76+ } ;
77+
78+ const main = async ( ) => {
79+ // Load credentials dynamically from environment variable
80+ const keyFilePath = process . env . GOOGLE_APPLICATION_CREDENTIALS ;
81+ const localizationRoot = process . env . LOCALIZATION_ROOT ;
82+
83+ // Debug logging
84+ console . log ( 'Google API Key File Path:' , keyFilePath ) ;
85+ console . log ( 'Localization Root:' , localizationRoot ) ;
86+
87+ if ( ! keyFilePath || ! fs . existsSync ( keyFilePath ) ) {
88+ throw new Error ( 'Google API credentials file not found. Ensure GOOGLE_APPLICATION_CREDENTIALS is set.' ) ;
89+ }
90+
91+ if ( ! localizationRoot || ! fs . existsSync ( localizationRoot ) ) {
92+ throw new Error ( 'Localization root folder not found. Ensure LOCALIZATION_ROOT is set.' ) ;
93+ }
94+
95+ const auth = new google . auth . GoogleAuth ( {
96+ keyFile : keyFilePath ,
97+ scopes : [ 'https://www.googleapis.com/auth/spreadsheets' ] ,
98+ } ) ;
99+ const sheets = google . sheets ( { version : 'v4' , auth } ) ;
100+
101+ const spreadsheetId = process . env . SPREADSHEET_ID ;
102+
103+ // Get the list of existing sheet names
104+ const sheetInfo = await sheets . spreadsheets . get ( {
105+ spreadsheetId,
106+ } ) ;
107+ const existingSheetNames = sheetInfo . data . sheets . map ( sheet => sheet . properties . title ) ;
108+
109+ // Process the root folder and push data to the RootLocalization sheet if localization files exist
110+ const rootFiles = fs . readdirSync ( localizationRoot ) . filter ( file => file . endsWith ( '.json' ) ) ;
111+ if ( rootFiles . length > 0 ) {
112+ await processFolder ( localizationRoot , 'RootLocalization' , sheets , existingSheetNames , spreadsheetId ) ;
113+ }
114+
115+ // Process subfolders
116+ const subfolders = fs . readdirSync ( localizationRoot ) . filter ( subfolder => fs . lstatSync ( `${ localizationRoot } /${ subfolder } ` ) . isDirectory ( ) ) ;
117+ for ( const subfolder of subfolders ) {
118+ await processFolder ( `${ localizationRoot } /${ subfolder } ` , subfolder , sheets , existingSheetNames , spreadsheetId ) ;
119+ }
120+
121+ console . log ( 'Data successfully uploaded to Google Sheets' ) ;
122+ } ;
123+
124+ if ( require . main === module ) {
125+ main ( ) ;
126+ }
127+
128+ module . exports = { processFolder, parseLocalizationFiles } ;
0 commit comments