`sync`: Updates manifest and state files.
()
| 139 | |
| 140 | /** `sync`: Updates manifest and state files. */ |
| 141 | async function sync() { |
| 142 | console.log('Syncing i18n files...'); |
| 143 | |
| 144 | // 1. Update Manifest from source locale |
| 145 | const sourceMap = await getLocaleMap(SOURCE_LOCALE); |
| 146 | if (Object.keys(sourceMap).length === 0) { |
| 147 | console.error(`❌ Error: Could not load source locale "${SOURCE_LOCALE}". Check that the file exists and exports valid data.`); |
| 148 | process.exit(1); |
| 149 | } |
| 150 | |
| 151 | const newManifest = {}; |
| 152 | for (const key in sourceMap) { |
| 153 | newManifest[key] = hash(sourceMap[key]); |
| 154 | } |
| 155 | saveJson(MANIFEST_PATH, newManifest); |
| 156 | console.log(`✓ Generated manifest from "${SOURCE_LOCALE}.ts" with ${Object.keys(newManifest).length} keys.`); |
| 157 | |
| 158 | // 2. Update State file for all other locales |
| 159 | const allLocales = getAvailableLocales(); |
| 160 | const otherLocales = allLocales.filter(l => l !== SOURCE_LOCALE); |
| 161 | |
| 162 | if (otherLocales.length === 0) { |
| 163 | console.log('ℹ️ No other locale files found. Only manifest updated.'); |
| 164 | return; |
| 165 | } |
| 166 | |
| 167 | const currentState = loadJson(STATE_PATH); |
| 168 | const newState = {}; |
| 169 | |
| 170 | for (const locale of otherLocales) { |
| 171 | console.log(`Processing locale: ${locale}`); |
| 172 | newState[locale] = {}; |
| 173 | const translationMap = await getLocaleMap(locale); |
| 174 | |
| 175 | for (const key in newManifest) { |
| 176 | const sourceHash = newManifest[key]; |
| 177 | const translatedValue = translationMap[key]; |
| 178 | |
| 179 | if (translatedValue === undefined) { |
| 180 | // Key is missing from translation file |
| 181 | newState[locale][key] = null; |
| 182 | continue; |
| 183 | } |
| 184 | |
| 185 | const translationHash = hash(translatedValue); |
| 186 | const previousEntry = normalizeStateEntry(currentState[locale]?.[key]); |
| 187 | |
| 188 | let confirmedSource = previousEntry.source; |
| 189 | |
| 190 | if (previousEntry.source === sourceHash) { |
| 191 | confirmedSource = sourceHash; |
| 192 | } else if (previousEntry.translation && previousEntry.translation !== translationHash) { |
| 193 | confirmedSource = sourceHash; |
| 194 | } else if (!previousEntry.source) { |
| 195 | confirmedSource = sourceHash; |
| 196 | } |
| 197 | |
| 198 | newState[locale][key] = { |
no test coverage detected