waybetter 0.1.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -9
- package/bin/waybetter.mjs +46 -0
- package/build/runtime.mjs +105 -0
- package/cli/buildenv.mjs +130 -0
- package/cli/dev.mjs +97 -0
- package/cli/i18n.mjs +382 -0
- package/cli/manifests.mjs +383 -0
- package/cli/privacy.mjs +768 -0
- package/cli/release.mjs +444 -0
- package/cli/remote.mjs +260 -0
- package/cli/store.mjs +326 -0
- package/cli/strings.mjs +121 -0
- package/dist/runtime/column.d.ts +93 -0
- package/dist/runtime/column.js +451 -0
- package/dist/runtime/column.js.map +1 -0
- package/dist/runtime/commandReport.d.ts +19 -0
- package/dist/runtime/commandReport.js +47 -0
- package/dist/runtime/commandReport.js.map +1 -0
- package/dist/runtime/commands.d.ts +72 -0
- package/dist/runtime/commands.js +214 -0
- package/dist/runtime/commands.js.map +1 -0
- package/dist/runtime/devErrors.d.ts +16 -0
- package/dist/runtime/devErrors.js +30 -0
- package/dist/runtime/devErrors.js.map +1 -0
- package/dist/runtime/domHub.d.ts +21 -0
- package/dist/runtime/domHub.js +139 -4
- package/dist/runtime/domHub.js.map +1 -1
- package/dist/runtime/featureModules.d.ts +157 -0
- package/dist/runtime/featureModules.js +484 -0
- package/dist/runtime/featureModules.js.map +1 -0
- package/dist/runtime/featureTable.d.ts +144 -0
- package/dist/runtime/featureTable.js +223 -0
- package/dist/runtime/featureTable.js.map +1 -0
- package/dist/runtime/fonts.d.ts +22 -0
- package/dist/runtime/fonts.js +72 -0
- package/dist/runtime/fonts.js.map +1 -0
- package/dist/runtime/i18n.d.ts +138 -0
- package/dist/runtime/i18n.js +614 -0
- package/dist/runtime/i18n.js.map +1 -0
- package/dist/runtime/i18nCheck.d.ts +30 -0
- package/dist/runtime/i18nCheck.js +224 -0
- package/dist/runtime/i18nCheck.js.map +1 -0
- package/dist/runtime/pageLang.d.ts +8 -0
- package/dist/runtime/pageLang.js +64 -0
- package/dist/runtime/pageLang.js.map +1 -0
- package/dist/runtime/pageStrings.d.ts +35 -0
- package/dist/runtime/pageStrings.js +76 -0
- package/dist/runtime/pageStrings.js.map +1 -0
- package/dist/runtime/panelButton.d.ts +33 -0
- package/dist/runtime/panelButton.js +83 -0
- package/dist/runtime/panelButton.js.map +1 -0
- package/dist/runtime/permissions.d.ts +47 -0
- package/dist/runtime/permissions.js +141 -0
- package/dist/runtime/permissions.js.map +1 -0
- package/dist/runtime/pluginApi.d.ts +51 -2
- package/dist/runtime/pluginApi.js +137 -22
- package/dist/runtime/pluginApi.js.map +1 -1
- package/dist/runtime/pluginI18n.d.ts +29 -0
- package/dist/runtime/pluginI18n.js +119 -0
- package/dist/runtime/pluginI18n.js.map +1 -0
- package/dist/runtime/settingsForm.d.ts +66 -0
- package/dist/runtime/settingsForm.js +114 -0
- package/dist/runtime/settingsForm.js.map +1 -0
- package/dist/runtime/site.d.ts +5 -0
- package/dist/runtime/site.js +1 -1
- package/dist/runtime/site.js.map +1 -1
- package/dist/runtime/siteRuntime.d.ts +144 -0
- package/dist/runtime/siteRuntime.js +175 -0
- package/dist/runtime/siteRuntime.js.map +1 -0
- package/dist/runtime/stringPackHook.d.ts +84 -0
- package/dist/runtime/stringPackHook.js +220 -0
- package/dist/runtime/stringPackHook.js.map +1 -0
- package/dist/runtime/stringPackTranslate.d.ts +59 -0
- package/dist/runtime/stringPackTranslate.js +264 -0
- package/dist/runtime/stringPackTranslate.js.map +1 -0
- package/dist/runtime/stringPacks.d.ts +200 -0
- package/dist/runtime/stringPacks.js +474 -0
- package/dist/runtime/stringPacks.js.map +1 -0
- package/dist/runtime/styles.d.ts +15 -0
- package/dist/runtime/styles.js +81 -0
- package/dist/runtime/styles.js.map +1 -0
- package/dist/runtime/textNet.d.ts +15 -0
- package/dist/runtime/textNet.js +131 -0
- package/dist/runtime/textNet.js.map +1 -0
- package/dist/runtime/themeApi.d.ts +121 -0
- package/dist/runtime/themeApi.js +220 -0
- package/dist/runtime/themeApi.js.map +1 -0
- package/dist/runtime/themeChoice.d.ts +52 -0
- package/dist/runtime/themeChoice.js +69 -0
- package/dist/runtime/themeChoice.js.map +1 -0
- package/dist/runtime/themeComponents.d.ts +435 -0
- package/dist/runtime/themeComponents.js +463 -0
- package/dist/runtime/themeComponents.js.map +1 -0
- package/dist/runtime/themeDecor.d.ts +73 -0
- package/dist/runtime/themeDecor.js +131 -0
- package/dist/runtime/themeDecor.js.map +1 -0
- package/dist/runtime/themeDoctor.d.ts +11 -0
- package/dist/runtime/themeDoctor.js +51 -0
- package/dist/runtime/themeDoctor.js.map +1 -0
- package/dist/runtime/themeIcons.d.ts +130 -0
- package/dist/runtime/themeIcons.js +263 -0
- package/dist/runtime/themeIcons.js.map +1 -0
- package/dist/runtime/themeRuntime.d.ts +100 -0
- package/dist/runtime/themeRuntime.js +497 -0
- package/dist/runtime/themeRuntime.js.map +1 -0
- package/dist/runtime/themeSchema.d.ts +10 -0
- package/dist/runtime/themeSchema.js +150 -0
- package/dist/runtime/themeSchema.js.map +1 -0
- package/dist/runtime/themeSpec.d.ts +259 -0
- package/dist/runtime/themeSpec.js +439 -0
- package/dist/runtime/themeSpec.js.map +1 -0
- package/dist/runtime/themeTokens.d.ts +12 -0
- package/dist/runtime/themeTokens.js +14 -6
- package/dist/runtime/themeTokens.js.map +1 -1
- package/dist/runtime/themeVariants.d.ts +30 -0
- package/dist/runtime/themeVariants.js +53 -0
- package/dist/runtime/themeVariants.js.map +1 -0
- package/dist/runtime/ui.d.ts +192 -0
- package/dist/runtime/ui.js +926 -0
- package/dist/runtime/ui.js.map +1 -0
- package/dist/shell/InstallDialog.d.ts +40 -0
- package/dist/shell/InstallDialog.js +170 -0
- package/dist/shell/InstallDialog.js.map +1 -0
- package/dist/shell/StoreView.d.ts +66 -0
- package/dist/shell/StoreView.js +103 -0
- package/dist/shell/StoreView.js.map +1 -0
- package/dist/shell/addressModel.js.map +1 -1
- package/dist/shell/chrome.js.map +1 -1
- package/dist/shell/deckModel.d.ts +117 -0
- package/dist/shell/deckModel.js +267 -0
- package/dist/shell/deckModel.js.map +1 -0
- package/dist/shell/frame/AccountSwitcher.d.ts +42 -0
- package/dist/shell/frame/AccountSwitcher.js +243 -0
- package/dist/shell/frame/AccountSwitcher.js.map +1 -0
- package/dist/shell/frame/AddColumnDialog.d.ts +8 -0
- package/dist/shell/frame/AddColumnDialog.js +81 -0
- package/dist/shell/frame/AddColumnDialog.js.map +1 -0
- package/dist/shell/frame/AppMenu.d.ts +21 -0
- package/dist/shell/frame/AppMenu.js +642 -0
- package/dist/shell/frame/AppMenu.js.map +1 -0
- package/dist/shell/frame/CommandPalette.d.ts +7 -0
- package/dist/shell/frame/CommandPalette.js +118 -0
- package/dist/shell/frame/CommandPalette.js.map +1 -0
- package/dist/shell/frame/DeckView.d.ts +13 -0
- package/dist/shell/frame/DeckView.js +287 -0
- package/dist/shell/frame/DeckView.js.map +1 -0
- package/dist/shell/frame/FindBar.d.ts +10 -0
- package/dist/shell/frame/FindBar.js +108 -0
- package/dist/shell/frame/FindBar.js.map +1 -0
- package/dist/shell/frame/MediaPanel.d.ts +8 -0
- package/dist/shell/frame/MediaPanel.js +76 -0
- package/dist/shell/frame/MediaPanel.js.map +1 -0
- package/dist/shell/frame/NewTabPage.d.ts +9 -0
- package/dist/shell/frame/NewTabPage.js +71 -0
- package/dist/shell/frame/NewTabPage.js.map +1 -0
- package/dist/shell/frame/PaneTheme.d.ts +16 -0
- package/dist/shell/frame/PaneTheme.js +67 -0
- package/dist/shell/frame/PaneTheme.js.map +1 -0
- package/dist/shell/frame/ReportDialog.d.ts +3 -0
- package/dist/shell/frame/ReportDialog.js +95 -0
- package/dist/shell/frame/ReportDialog.js.map +1 -0
- package/dist/shell/frame/Shell.d.ts +8 -0
- package/dist/shell/frame/Shell.js +1131 -0
- package/dist/shell/frame/Shell.js.map +1 -0
- package/dist/shell/frame/Titlebar.d.ts +16 -0
- package/dist/shell/frame/Titlebar.js +77 -0
- package/dist/shell/frame/Titlebar.js.map +1 -0
- package/dist/shell/frame/TitlebarExtras.d.ts +4 -0
- package/dist/shell/frame/TitlebarExtras.js +202 -0
- package/dist/shell/frame/TitlebarExtras.js.map +1 -0
- package/dist/shell/frame/WebPanel.d.ts +4 -0
- package/dist/shell/frame/WebPanel.js +182 -0
- package/dist/shell/frame/WebPanel.js.map +1 -0
- package/dist/shell/frame/accountModel.d.ts +49 -0
- package/dist/shell/frame/accountModel.js +67 -0
- package/dist/shell/frame/accountModel.js.map +1 -0
- package/dist/shell/frame/accountSwitcher.css +91 -0
- package/dist/shell/frame/appI18n.d.ts +44 -0
- package/dist/shell/frame/appI18n.js +64 -0
- package/dist/shell/frame/appI18n.js.map +1 -0
- package/dist/shell/frame/appMenu.css +121 -0
- package/dist/shell/frame/backupModel.d.ts +38 -0
- package/dist/shell/frame/backupModel.js +192 -0
- package/dist/shell/frame/backupModel.js.map +1 -0
- package/dist/shell/frame/boot.d.ts +8 -0
- package/dist/shell/frame/boot.js +35 -0
- package/dist/shell/frame/boot.js.map +1 -0
- package/dist/shell/frame/brand.d.ts +1 -0
- package/dist/shell/frame/brand.js +4 -0
- package/dist/shell/frame/brand.js.map +1 -0
- package/dist/shell/frame/bridge.d.ts +35 -0
- package/dist/shell/frame/bridge.js +70 -0
- package/dist/shell/frame/bridge.js.map +1 -0
- package/dist/shell/frame/chromeTheme.d.ts +29 -0
- package/dist/shell/frame/chromeTheme.js +81 -0
- package/dist/shell/frame/chromeTheme.js.map +1 -0
- package/dist/shell/frame/deck.css +209 -0
- package/dist/shell/frame/deckStore.d.ts +89 -0
- package/dist/shell/frame/deckStore.js +239 -0
- package/dist/shell/frame/deckStore.js.map +1 -0
- package/dist/shell/frame/devHost.d.ts +35 -0
- package/dist/shell/frame/devHost.js +80 -0
- package/dist/shell/frame/devHost.js.map +1 -0
- package/dist/shell/frame/devModel.d.ts +7 -0
- package/dist/shell/frame/devModel.js +17 -0
- package/dist/shell/frame/devModel.js.map +1 -0
- package/dist/shell/frame/diag.d.ts +7 -0
- package/dist/shell/frame/diag.js +39 -0
- package/dist/shell/frame/diag.js.map +1 -0
- package/dist/shell/frame/findBar.css +14 -0
- package/dist/shell/frame/frameMessages.d.ts +248 -0
- package/dist/shell/frame/frameMessages.js +252 -0
- package/dist/shell/frame/frameMessages.js.map +1 -0
- package/dist/shell/frame/hooks.d.ts +39 -0
- package/dist/shell/frame/hooks.js +97 -0
- package/dist/shell/frame/hooks.js.map +1 -0
- package/dist/shell/frame/i18n.d.ts +27 -0
- package/dist/shell/frame/i18n.js +66 -0
- package/dist/shell/frame/i18n.js.map +1 -0
- package/dist/shell/frame/iconPack.d.ts +11 -0
- package/dist/shell/frame/iconPack.js +45 -0
- package/dist/shell/frame/iconPack.js.map +1 -0
- package/dist/shell/frame/icons.d.ts +71 -0
- package/dist/shell/frame/icons.js +75 -0
- package/dist/shell/frame/icons.js.map +1 -0
- package/dist/shell/frame/index.d.ts +34 -0
- package/dist/shell/frame/index.js +43 -0
- package/dist/shell/frame/index.js.map +1 -0
- package/dist/shell/frame/language.d.ts +58 -0
- package/dist/shell/frame/language.js +165 -0
- package/dist/shell/frame/language.js.map +1 -0
- package/dist/shell/frame/mediaModel.d.ts +34 -0
- package/dist/shell/frame/mediaModel.js +53 -0
- package/dist/shell/frame/mediaModel.js.map +1 -0
- package/dist/shell/frame/menuMessages.en.json +54 -0
- package/dist/shell/frame/menuModel.d.ts +277 -0
- package/dist/shell/frame/menuModel.js +293 -0
- package/dist/shell/frame/menuModel.js.map +1 -0
- package/dist/shell/frame/paletteModel.d.ts +139 -0
- package/dist/shell/frame/paletteModel.js +112 -0
- package/dist/shell/frame/paletteModel.js.map +1 -0
- package/dist/shell/frame/paneTheme.css +9 -0
- package/dist/shell/frame/pluginCommandStore.d.ts +23 -0
- package/dist/shell/frame/pluginCommandStore.js +70 -0
- package/dist/shell/frame/pluginCommandStore.js.map +1 -0
- package/dist/shell/frame/reportModel.d.ts +52 -0
- package/dist/shell/frame/reportModel.js +105 -0
- package/dist/shell/frame/reportModel.js.map +1 -0
- package/dist/shell/frame/safeStore.d.ts +7 -0
- package/dist/shell/frame/safeStore.js +40 -0
- package/dist/shell/frame/safeStore.js.map +1 -0
- package/dist/shell/frame/searchInput.d.ts +2 -0
- package/dist/shell/frame/searchInput.js +11 -0
- package/dist/shell/frame/searchInput.js.map +1 -0
- package/dist/shell/frame/shell.css +629 -0
- package/dist/shell/frame/site.d.ts +206 -0
- package/dist/shell/frame/site.js +22 -0
- package/dist/shell/frame/site.js.map +1 -0
- package/dist/shell/frame/state.d.ts +99 -0
- package/dist/shell/frame/state.js +284 -0
- package/dist/shell/frame/state.js.map +1 -0
- package/dist/shell/frame/syncGate.d.ts +10 -0
- package/dist/shell/frame/syncGate.js +36 -0
- package/dist/shell/frame/syncGate.js.map +1 -0
- package/dist/shell/frame/syncHost.d.ts +35 -0
- package/dist/shell/frame/syncHost.js +85 -0
- package/dist/shell/frame/syncHost.js.map +1 -0
- package/dist/shell/frame/tabStill.d.ts +2 -0
- package/dist/shell/frame/tabStill.js +62 -0
- package/dist/shell/frame/tabStill.js.map +1 -0
- package/dist/shell/frame/themeScopes.d.ts +29 -0
- package/dist/shell/frame/themeScopes.js +61 -0
- package/dist/shell/frame/themeScopes.js.map +1 -0
- package/dist/shell/frame/themeStore.d.ts +99 -0
- package/dist/shell/frame/themeStore.js +252 -0
- package/dist/shell/frame/themeStore.js.map +1 -0
- package/dist/shell/frame/windowBinding.d.ts +2 -0
- package/dist/shell/frame/windowBinding.js +7 -0
- package/dist/shell/frame/windowBinding.js.map +1 -0
- package/dist/shell/frame/workspaceModel.d.ts +82 -0
- package/dist/shell/frame/workspaceModel.js +250 -0
- package/dist/shell/frame/workspaceModel.js.map +1 -0
- package/dist/shell/frame/workspaces.css +84 -0
- package/dist/shell/frame/workspaces.d.ts +22 -0
- package/dist/shell/frame/workspaces.js +125 -0
- package/dist/shell/frame/workspaces.js.map +1 -0
- package/dist/shell/frame/zoomStore.d.ts +10 -0
- package/dist/shell/frame/zoomStore.js +65 -0
- package/dist/shell/frame/zoomStore.js.map +1 -0
- package/dist/shell/installController.d.ts +122 -0
- package/dist/shell/installController.js +146 -0
- package/dist/shell/installController.js.map +1 -0
- package/dist/shell/installerMessages.d.ts +30 -0
- package/dist/shell/installerMessages.js +36 -0
- package/dist/shell/installerMessages.js.map +1 -0
- package/dist/shell/linkDrop.js.map +1 -1
- package/dist/shell/messages.d.ts +16 -0
- package/dist/shell/messages.js +27 -0
- package/dist/shell/messages.js.map +1 -0
- package/dist/shell/palette.js.map +1 -1
- package/dist/shell/paneModel.d.ts +22 -0
- package/dist/shell/paneModel.js +24 -1
- package/dist/shell/paneModel.js.map +1 -1
- package/dist/shell/panel/Appearance.d.ts +8 -0
- package/dist/shell/panel/Appearance.js +256 -0
- package/dist/shell/panel/Appearance.js.map +1 -0
- package/dist/shell/panel/BackupPanel.d.ts +5 -0
- package/dist/shell/panel/BackupPanel.js +198 -0
- package/dist/shell/panel/BackupPanel.js.map +1 -0
- package/dist/shell/panel/DeveloperPanel.d.ts +4 -0
- package/dist/shell/panel/DeveloperPanel.js +51 -0
- package/dist/shell/panel/DeveloperPanel.js.map +1 -0
- package/dist/shell/panel/FeatureToggles.d.ts +13 -0
- package/dist/shell/panel/FeatureToggles.js +42 -0
- package/dist/shell/panel/FeatureToggles.js.map +1 -0
- package/dist/shell/panel/Home.d.ts +3 -0
- package/dist/shell/panel/Home.js +23 -0
- package/dist/shell/panel/Home.js.map +1 -0
- package/dist/shell/panel/IconPackInstall.d.ts +15 -0
- package/dist/shell/panel/IconPackInstall.js +41 -0
- package/dist/shell/panel/IconPackInstall.js.map +1 -0
- package/dist/shell/panel/LanguageSettings.d.ts +1 -0
- package/dist/shell/panel/LanguageSettings.js +54 -0
- package/dist/shell/panel/LanguageSettings.js.map +1 -0
- package/dist/shell/panel/MakePanel.d.ts +3 -0
- package/dist/shell/panel/MakePanel.js +237 -0
- package/dist/shell/panel/MakePanel.js.map +1 -0
- package/dist/shell/panel/MarkdownDoc.d.ts +6 -0
- package/dist/shell/panel/MarkdownDoc.js +35 -0
- package/dist/shell/panel/MarkdownDoc.js.map +1 -0
- package/dist/shell/panel/Modes.d.ts +40 -0
- package/dist/shell/panel/Modes.js +270 -0
- package/dist/shell/panel/Modes.js.map +1 -0
- package/dist/shell/panel/NavIcon.d.ts +4 -0
- package/dist/shell/panel/NavIcon.js +6 -0
- package/dist/shell/panel/NavIcon.js.map +1 -0
- package/dist/shell/panel/Panel.d.ts +7 -0
- package/dist/shell/panel/Panel.js +139 -0
- package/dist/shell/panel/Panel.js.map +1 -0
- package/dist/shell/panel/PluginFeatures.d.ts +24 -0
- package/dist/shell/panel/PluginFeatures.js +165 -0
- package/dist/shell/panel/PluginFeatures.js.map +1 -0
- package/dist/shell/panel/Plugins.d.ts +33 -0
- package/dist/shell/panel/Plugins.js +112 -0
- package/dist/shell/panel/Plugins.js.map +1 -0
- package/dist/shell/panel/PowerSettings.d.ts +4 -0
- package/dist/shell/panel/PowerSettings.js +52 -0
- package/dist/shell/panel/PowerSettings.js.map +1 -0
- package/dist/shell/panel/Settings.d.ts +23 -0
- package/dist/shell/panel/Settings.js +116 -0
- package/dist/shell/panel/Settings.js.map +1 -0
- package/dist/shell/panel/ShareSetup.d.ts +8 -0
- package/dist/shell/panel/ShareSetup.js +130 -0
- package/dist/shell/panel/ShareSetup.js.map +1 -0
- package/dist/shell/panel/StoreSection.d.ts +6 -0
- package/dist/shell/panel/StoreSection.js +48 -0
- package/dist/shell/panel/StoreSection.js.map +1 -0
- package/dist/shell/panel/StringPacks.d.ts +11 -0
- package/dist/shell/panel/StringPacks.js +106 -0
- package/dist/shell/panel/StringPacks.js.map +1 -0
- package/dist/shell/panel/ThemeBuilder.d.ts +5 -0
- package/dist/shell/panel/ThemeBuilder.js +205 -0
- package/dist/shell/panel/ThemeBuilder.js.map +1 -0
- package/dist/shell/panel/backup.css +34 -0
- package/dist/shell/panel/builder.css +232 -0
- package/dist/shell/panel/builderModel.d.ts +55 -0
- package/dist/shell/panel/builderModel.js +95 -0
- package/dist/shell/panel/builderModel.js.map +1 -0
- package/dist/shell/panel/compare.d.ts +10 -0
- package/dist/shell/panel/compare.js +51 -0
- package/dist/shell/panel/compare.js.map +1 -0
- package/dist/shell/panel/controls.d.ts +135 -0
- package/dist/shell/panel/controls.js +213 -0
- package/dist/shell/panel/controls.js.map +1 -0
- package/dist/shell/panel/featureModel.d.ts +69 -0
- package/dist/shell/panel/featureModel.js +79 -0
- package/dist/shell/panel/featureModel.js.map +1 -0
- package/dist/shell/panel/fonts/FontBrowser.d.ts +10 -0
- package/dist/shell/panel/fonts/FontBrowser.js +189 -0
- package/dist/shell/panel/fonts/FontBrowser.js.map +1 -0
- package/dist/shell/panel/fonts/FontRoles.d.ts +20 -0
- package/dist/shell/panel/fonts/FontRoles.js +77 -0
- package/dist/shell/panel/fonts/FontRoles.js.map +1 -0
- package/dist/shell/panel/fonts/catalog.d.ts +37 -0
- package/dist/shell/panel/fonts/catalog.js +68 -0
- package/dist/shell/panel/fonts/catalog.js.map +1 -0
- package/dist/shell/panel/fonts/googleFontsCatalog.json +1 -0
- package/dist/shell/panel/index.d.ts +20 -0
- package/dist/shell/panel/index.js +34 -0
- package/dist/shell/panel/index.js.map +1 -0
- package/dist/shell/panel/languageModel.d.ts +5 -0
- package/dist/shell/panel/languageModel.js +7 -0
- package/dist/shell/panel/languageModel.js.map +1 -0
- package/dist/shell/panel/make.css +72 -0
- package/dist/shell/panel/makeModel.d.ts +32 -0
- package/dist/shell/panel/makeModel.js +84 -0
- package/dist/shell/panel/makeModel.js.map +1 -0
- package/dist/shell/panel/markdown.d.ts +46 -0
- package/dist/shell/panel/markdown.js +100 -0
- package/dist/shell/panel/markdown.js.map +1 -0
- package/dist/shell/panel/nav.d.ts +12 -0
- package/dist/shell/panel/nav.js +50 -0
- package/dist/shell/panel/nav.js.map +1 -0
- package/dist/shell/panel/panel.css +401 -0
- package/dist/shell/panel/panelMessages.d.ts +763 -0
- package/dist/shell/panel/panelMessages.js +767 -0
- package/dist/shell/panel/panelMessages.js.map +1 -0
- package/dist/shell/panel/plugins.css +59 -0
- package/dist/shell/panel/setupModel.d.ts +87 -0
- package/dist/shell/panel/setupModel.js +152 -0
- package/dist/shell/panel/setupModel.js.map +1 -0
- package/dist/shell/panel/site.d.ts +259 -0
- package/dist/shell/panel/site.js +25 -0
- package/dist/shell/panel/site.js.map +1 -0
- package/dist/shell/panel/strings.css +7 -0
- package/dist/shell/panel/themes.d.ts +10 -0
- package/dist/shell/panel/themes.js +8 -0
- package/dist/shell/panel/themes.js.map +1 -0
- package/dist/shell/profileModel.d.ts +3 -2
- package/dist/shell/profileModel.js +7 -5
- package/dist/shell/profileModel.js.map +1 -1
- package/dist/shell/store.css +230 -0
- package/dist/shell/storeMessages.d.ts +169 -0
- package/dist/shell/storeMessages.js +172 -0
- package/dist/shell/storeMessages.js.map +1 -0
- package/dist/shell/storeModel.d.ts +181 -0
- package/dist/shell/storeModel.js +133 -0
- package/dist/shell/storeModel.js.map +1 -0
- package/dist/shell/stringPacksModel.d.ts +44 -0
- package/dist/shell/stringPacksModel.js +94 -0
- package/dist/shell/stringPacksModel.js.map +1 -0
- package/dist/shell/updateModel.d.ts +2 -1
- package/dist/shell/updateModel.js +5 -4
- package/dist/shell/updateModel.js.map +1 -1
- package/dist/shell/windowControls.d.ts +4 -0
- package/dist/shell/windowControls.js +5 -0
- package/dist/shell/windowControls.js.map +1 -1
- package/i18n-config.schema.json +29 -0
- package/i18n-meta.schema.json +26 -0
- package/i18n.schema.json +42 -0
- package/icons.schema.json +646 -0
- package/languages.schema.json +23 -0
- package/locales/ar-x-fm.json +11 -0
- package/locales/ar.json +1281 -0
- package/locales/bg.json +1280 -0
- package/locales/bn.json +1280 -0
- package/locales/ca.json +1280 -0
- package/locales/cs.json +1280 -0
- package/locales/da.json +1280 -0
- package/locales/de.json +1280 -0
- package/locales/el.json +1280 -0
- package/locales/en-GB.json +27 -0
- package/locales/en.json +1280 -0
- package/locales/en.meta.json +51 -0
- package/locales/es.json +1280 -0
- package/locales/eu.json +1280 -0
- package/locales/fa.json +1281 -0
- package/locales/fi.json +1280 -0
- package/locales/fil.json +1280 -0
- package/locales/fr.json +1280 -0
- package/locales/ga.json +1280 -0
- package/locales/gl.json +1280 -0
- package/locales/gu.json +1280 -0
- package/locales/ha.json +1280 -0
- package/locales/he.json +1281 -0
- package/locales/hi.json +1280 -0
- package/locales/hr.json +1280 -0
- package/locales/hu.json +1279 -0
- package/locales/id.json +1280 -0
- package/locales/ig.json +1280 -0
- package/locales/it.json +1280 -0
- package/locales/ja.json +1280 -0
- package/locales/kn.json +1280 -0
- package/locales/ko.json +1280 -0
- package/locales/mr.json +1280 -0
- package/locales/ms.json +1280 -0
- package/locales/nb.json +1280 -0
- package/locales/nl.json +1280 -0
- package/locales/pl.json +1280 -0
- package/locales/pt.json +1280 -0
- package/locales/ro.json +1280 -0
- package/locales/ru.json +1280 -0
- package/locales/sk.json +1280 -0
- package/locales/sr.json +1280 -0
- package/locales/sv.json +1280 -0
- package/locales/ta.json +1280 -0
- package/locales/th.json +1280 -0
- package/locales/tr.json +1280 -0
- package/locales/uk.json +1280 -0
- package/locales/ur.json +1281 -0
- package/locales/vi.json +1280 -0
- package/locales/yo.json +1280 -0
- package/locales/zh-Hans.json +1280 -0
- package/locales/zh-Hant.json +1280 -0
- package/package.json +148 -6
- package/store-catalog.schema.json +65 -0
- package/theme.schema.json +4659 -0
- package/windows/installer.nsi +926 -0
- package/windows/languages/Basque.nsh +28 -0
- package/windows/languages/Catalan.nsh +28 -0
- package/windows/languages/Croatian.nsh +28 -0
- package/windows/languages/Czech.nsh +28 -0
- package/windows/languages/Danish.nsh +28 -0
- package/windows/languages/Finnish.nsh +28 -0
- package/windows/languages/Galician.nsh +28 -0
- package/windows/languages/Greek.nsh +28 -0
- package/windows/languages/Hungarian.nsh +28 -0
- package/windows/languages/Indonesian.nsh +28 -0
- package/windows/languages/Irish.nsh +28 -0
- package/windows/languages/Malay.nsh +28 -0
- package/windows/languages/Polish.nsh +28 -0
- package/windows/languages/Romanian.nsh +28 -0
- package/windows/languages/Serbian.nsh +28 -0
- package/windows/languages/Slovak.nsh +28 -0
- package/windows/languages/Thai.nsh +28 -0
package/cli/i18n.mjs
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
// `waybetter i18n check|extract|rename`: an app's locale catalogs against the framework's rules
|
|
2
|
+
// (waybetter/i18n/check: file shape, keys English does not have, ICU syntax, placeholder parity,
|
|
3
|
+
// plural forms, no markup or control characters, length warnings), the files generated from them,
|
|
4
|
+
// and the keys the app's code looks up.
|
|
5
|
+
//
|
|
6
|
+
// waybetter i18n check check every catalog (exit 1 on errors)
|
|
7
|
+
// waybetter i18n check --write also regenerate languages.json and the native localization files
|
|
8
|
+
// waybetter i18n check --verbose list every warning (untranslated and long messages)
|
|
9
|
+
// waybetter i18n check tr de only these locales (plus English)
|
|
10
|
+
// waybetter i18n extract keys the code looks up that English lacks (exit 1), then
|
|
11
|
+
// English keys no literal lookup names
|
|
12
|
+
// waybetter i18n extract --missing only the missing keys
|
|
13
|
+
// waybetter i18n rename --map <file> renames keys in every catalog ({ "old.key": "new.key" }), values carried
|
|
14
|
+
// waybetter i18n rename --map <file> --copy the same, keeping the old keys too
|
|
15
|
+
//
|
|
16
|
+
// Config: waybetter.i18n.json in the app's root (or --config <file>); every path is relative to it.
|
|
17
|
+
//
|
|
18
|
+
// {
|
|
19
|
+
// "locales": "locales", // <bcp47>.json, en.meta.json, the generated languages.json
|
|
20
|
+
// "framework": "node_modules/waybetter/locales", // default: this package's catalogs
|
|
21
|
+
// "sources": ["src"], // t('key'), tx('key'), coreText('key'), i18n.t('key')
|
|
22
|
+
// "nativeSources": ["src-tauri/src"], // tr(app, "native.key", ...), trf(...)
|
|
23
|
+
// "bundledPlugins": "src-tauri/bundled-plugins", // their inline English must match en.json
|
|
24
|
+
// "runtimeKeys": ["plugin.", "native.app."], // prefixes of keys built at runtime or used by generated files
|
|
25
|
+
// "supported": ["en", "tr", "de"], // the supported tier; every other catalog is "community" (default: all supported)
|
|
26
|
+
// "native": { "tauriDir": "src-tauri", "desktopFile": "linux/app.desktop" }
|
|
27
|
+
// }
|
|
28
|
+
//
|
|
29
|
+
// With "native", `--write` generates (and the plain check compares): macOS `Info.plist`
|
|
30
|
+
// (CFBundleLocalizations) and `macos/<lang>.lproj/InfoPlist.strings` with `tauri.macos.conf.json`
|
|
31
|
+
// listing them, and the Linux .desktop template with Name[xx]/Comment[xx] (`native.app.name`,
|
|
32
|
+
// `native.app.comment`). The Windows installer's languages ship with this package
|
|
33
|
+
// (windows/languages/*.nsh, generated from the framework catalogs).
|
|
34
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
|
|
35
|
+
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
36
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
37
|
+
|
|
38
|
+
export const I18N_CONFIG_FILE = 'waybetter.i18n.json';
|
|
39
|
+
|
|
40
|
+
export const I18N_USAGE = `Usage:
|
|
41
|
+
waybetter i18n check [--write] [--verbose] [locale…] [--config <file>]
|
|
42
|
+
Checks every locale catalog against English and the framework's rules; with --write also
|
|
43
|
+
regenerates languages.json and the native localization files (macOS, Linux).
|
|
44
|
+
waybetter i18n extract [--missing] [--config <file>]
|
|
45
|
+
Keys the code looks up that English lacks, and English keys without a literal lookup.
|
|
46
|
+
waybetter i18n rename --map <file> [--copy] [--config <file>]
|
|
47
|
+
Renames keys in every catalog of the app (and en.meta.json) by a { "old.key": "new.key" } map,
|
|
48
|
+
carrying each language's value; --copy keeps the old keys as well.
|
|
49
|
+
|
|
50
|
+
Config: ${I18N_CONFIG_FILE} in the app's root (locales, framework, sources, nativeSources,
|
|
51
|
+
bundledPlugins, runtimeKeys, native).`;
|
|
52
|
+
|
|
53
|
+
class I18nError extends Error {}
|
|
54
|
+
|
|
55
|
+
const read = file => JSON.parse(readFileSync(file, 'utf8'));
|
|
56
|
+
const CATALOG = /^[a-z]{2,3}(-[A-Za-z0-9]+)*\.json$/;
|
|
57
|
+
const catalogFiles = dir => readdirSync(dir).filter(file => CATALOG.test(file) && file !== 'languages.json');
|
|
58
|
+
const walk = (dir, pattern) => readdirSync(dir).flatMap(name => {
|
|
59
|
+
const path = join(dir, name);
|
|
60
|
+
return statSync(path).isDirectory() ? walk(path, pattern) : pattern.test(name) ? [path] : [];
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/** The catalog checks: the framework's sources inside its repository, else the built package. */
|
|
64
|
+
async function loadChecks() {
|
|
65
|
+
const source = fileURLToPath(new URL('../../runtime/src/i18nCheck.ts', import.meta.url));
|
|
66
|
+
const built = fileURLToPath(new URL('../dist/runtime/i18nCheck.js', import.meta.url));
|
|
67
|
+
const file = existsSync(source) ? source : built;
|
|
68
|
+
if (!existsSync(file)) throw new I18nError('the catalog checks are not built (run the package build)');
|
|
69
|
+
return import(pathToFileURL(file).href);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Reads and resolves the config (paths absolute). */
|
|
73
|
+
export function loadI18nConfig(cwd, file) {
|
|
74
|
+
const path = resolve(cwd, file ?? I18N_CONFIG_FILE);
|
|
75
|
+
if (!existsSync(path)) throw new I18nError(`${relative(cwd, path) || path} not found (see \`waybetter i18n --help\`)`);
|
|
76
|
+
let raw;
|
|
77
|
+
try { raw = read(path); } catch (error) { throw new I18nError(`${path}: ${error.message}`); }
|
|
78
|
+
const root = dirname(path);
|
|
79
|
+
const at = value => (isAbsolute(value) ? value : join(root, value));
|
|
80
|
+
const list = value => (Array.isArray(value) ? value : value ? [value] : []);
|
|
81
|
+
if (typeof raw.locales !== 'string') throw new I18nError(`${I18N_CONFIG_FILE}: "locales" (the catalog folder) is required`);
|
|
82
|
+
const native = raw.native && typeof raw.native === 'object' ? raw.native : null;
|
|
83
|
+
if (native && typeof native.tauriDir !== 'string') throw new I18nError(`${I18N_CONFIG_FILE}: "native.tauriDir" is required`);
|
|
84
|
+
return {
|
|
85
|
+
root,
|
|
86
|
+
locales: at(raw.locales),
|
|
87
|
+
framework: raw.framework ? at(raw.framework) : fileURLToPath(new URL('../locales', import.meta.url)),
|
|
88
|
+
sources: list(raw.sources ?? 'src').map(at),
|
|
89
|
+
nativeSources: list(raw.nativeSources).map(at),
|
|
90
|
+
bundledPlugins: raw.bundledPlugins ? at(raw.bundledPlugins) : null,
|
|
91
|
+
runtimeKeys: list(raw.runtimeKeys ?? ['plugin.', 'native.app.']),
|
|
92
|
+
supported: Array.isArray(raw.supported) ? raw.supported : null,
|
|
93
|
+
native: native ? { tauriDir: at(native.tauriDir), desktopFile: native.desktopFile ?? null, macos: native.macos !== false } : null,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ---- Native localization files ------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
/** Catalog locale -> Apple localization id (none for private-use tags). */
|
|
100
|
+
const apple = code => (code.includes('-x-') ? null : code);
|
|
101
|
+
const plistEscape = text => text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
102
|
+
const stringsEscape = text => text.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
103
|
+
const desktopEscape = text => text.replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/;/g, '\\;');
|
|
104
|
+
|
|
105
|
+
/** `[path, content]` of every generated native file: `catalogs` are the app's, English first. */
|
|
106
|
+
export function renderNative(config, en, catalogs) {
|
|
107
|
+
const { tauriDir, desktopFile, macos } = config.native;
|
|
108
|
+
const from = relative(config.root, config.locales).replace(/\\/g, '/');
|
|
109
|
+
const out = [];
|
|
110
|
+
if (macos) {
|
|
111
|
+
const codes = catalogs.map(catalog => apple(catalog.locale)).filter(Boolean);
|
|
112
|
+
out.push([join(tauriDir, 'Info.plist'), [
|
|
113
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
114
|
+
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
|
|
115
|
+
`<!-- Generated by \`waybetter i18n check --write\` from ${from}. Merged into the app bundle by Tauri. -->`,
|
|
116
|
+
'<plist version="1.0">',
|
|
117
|
+
'<dict>',
|
|
118
|
+
' <key>CFBundleDevelopmentRegion</key>',
|
|
119
|
+
' <string>en</string>',
|
|
120
|
+
' <key>CFBundleAllowMixedLocalizations</key>',
|
|
121
|
+
' <true/>',
|
|
122
|
+
' <key>CFBundleLocalizations</key>',
|
|
123
|
+
' <array>',
|
|
124
|
+
...codes.map(code => ` <string>${plistEscape(code)}</string>`),
|
|
125
|
+
' </array>',
|
|
126
|
+
'</dict>',
|
|
127
|
+
'</plist>',
|
|
128
|
+
'',
|
|
129
|
+
].join('\n')]);
|
|
130
|
+
const files = {};
|
|
131
|
+
for (const catalog of catalogs) {
|
|
132
|
+
const code = apple(catalog.locale);
|
|
133
|
+
if (!code) continue;
|
|
134
|
+
const name = catalog.messages['native.app.name'] ?? en.messages['native.app.name'];
|
|
135
|
+
if (name === undefined) throw new I18nError('en.json needs "native.app.name" (the app\'s name on macOS and Linux)');
|
|
136
|
+
const path = `macos/${code}.lproj/InfoPlist.strings`;
|
|
137
|
+
files[`Resources/${code}.lproj/InfoPlist.strings`] = path;
|
|
138
|
+
out.push([join(tauriDir, path), `/* Generated from ${from}/${catalog.locale}.json (\`waybetter i18n check --write\`). */\n"CFBundleDisplayName" = "${stringsEscape(name)}";\n"CFBundleName" = "${stringsEscape(name)}";\n`]);
|
|
139
|
+
}
|
|
140
|
+
out.push([join(tauriDir, 'tauri.macos.conf.json'), `${JSON.stringify({ bundle: { macOS: { files } } }, null, 2)}\n`]);
|
|
141
|
+
}
|
|
142
|
+
if (desktopFile) {
|
|
143
|
+
const desktop = [
|
|
144
|
+
'[Desktop Entry]',
|
|
145
|
+
`# Generated by \`waybetter i18n check --write\` from ${from} (a Tauri .desktop template).`,
|
|
146
|
+
'Categories={{categories}}',
|
|
147
|
+
'{{#if comment}}',
|
|
148
|
+
'Comment={{comment}}',
|
|
149
|
+
'{{/if}}',
|
|
150
|
+
];
|
|
151
|
+
for (const catalog of catalogs) {
|
|
152
|
+
if (catalog.locale === 'en' || !catalog.messages['native.app.comment']) continue;
|
|
153
|
+
desktop.push(`Comment[${catalog.locale.replace('-', '_')}]=${desktopEscape(catalog.messages['native.app.comment'])}`);
|
|
154
|
+
}
|
|
155
|
+
desktop.push('Exec={{exec}}', 'Icon={{icon}}', 'Name={{name}}');
|
|
156
|
+
for (const catalog of catalogs) {
|
|
157
|
+
if (catalog.locale === 'en' || !catalog.messages['native.app.name'] || catalog.messages['native.app.name'] === en.messages['native.app.name']) continue;
|
|
158
|
+
desktop.push(`Name[${catalog.locale.replace('-', '_')}]=${desktopEscape(catalog.messages['native.app.name'])}`);
|
|
159
|
+
}
|
|
160
|
+
desktop.push('Terminal=false', 'Type=Application', '{{#if mime_type}}', 'MimeType={{mime_type}}', '{{/if}}', '');
|
|
161
|
+
out.push([join(tauriDir, desktopFile), desktop.join('\n')]);
|
|
162
|
+
}
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ---- check ------------------------------------------------------------------------------------------
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Checks the catalogs. Returns `{ errors, warnings, lines }` (`lines`: what a terminal shows);
|
|
170
|
+
* with `write`, out-of-date generated files are rewritten instead of reported.
|
|
171
|
+
*/
|
|
172
|
+
export async function checkCatalogs(config, { write = false, verbose = false, only = [] } = {}) {
|
|
173
|
+
const { checkCatalog, checkShape, checkSource, coverage } = await loadChecks();
|
|
174
|
+
const lines = [];
|
|
175
|
+
let errors = 0;
|
|
176
|
+
let warnings = 0;
|
|
177
|
+
const label = path => relative(config.root, path).replace(/\\/g, '/');
|
|
178
|
+
const report = (issue, where) => {
|
|
179
|
+
const line = `${issue.level === 'error' ? 'ERROR' : 'warn '} ${where}${issue.key ? ` ${issue.key}` : ''}: ${issue.message}`;
|
|
180
|
+
if (issue.level === 'error') { errors += 1; lines.push(line); }
|
|
181
|
+
else { warnings += 1; if (verbose) lines.push(line); }
|
|
182
|
+
};
|
|
183
|
+
const metaOf = dir => {
|
|
184
|
+
if (!existsSync(join(dir, 'en.meta.json'))) return {};
|
|
185
|
+
const meta = read(join(dir, 'en.meta.json'));
|
|
186
|
+
delete meta.$schema;
|
|
187
|
+
return meta;
|
|
188
|
+
};
|
|
189
|
+
const APP = config.locales;
|
|
190
|
+
const KIT = config.framework;
|
|
191
|
+
|
|
192
|
+
// ---- Source (English)
|
|
193
|
+
const en = read(join(APP, 'en.json'));
|
|
194
|
+
const meta = metaOf(APP);
|
|
195
|
+
const kitEn = read(join(KIT, 'en.json'));
|
|
196
|
+
const kitMeta = metaOf(KIT);
|
|
197
|
+
for (const issue of [...checkShape(en, 'en.json'), ...checkSource(en, meta)]) report(issue, label(join(APP, 'en.json')));
|
|
198
|
+
for (const issue of [...checkShape(kitEn, 'en.json'), ...checkSource(kitEn, kitMeta)]) report(issue, label(join(KIT, 'en.json')));
|
|
199
|
+
for (const key of Object.keys(en.messages).filter(name => name in kitEn.messages)) {
|
|
200
|
+
report({ level: 'error', key, message: 'the framework catalog already defines this key' }, label(join(APP, 'en.json')));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Bundled plugins ship their English inline (so a copied file still works); it must match en.json.
|
|
204
|
+
if (config.bundledPlugins) {
|
|
205
|
+
for (const file of readdirSync(config.bundledPlugins).filter(name => name.endsWith('.plugin.js'))) {
|
|
206
|
+
const ns = file.replace(/\.plugin\.js$/, '');
|
|
207
|
+
const text = readFileSync(join(config.bundledPlugins, file), 'utf8');
|
|
208
|
+
const block = /\/\/ i18n:begin\r?\n([\s\S]*?)\/\/ i18n:end/.exec(text)?.[1];
|
|
209
|
+
const hosted = Object.fromEntries(Object.entries(en.messages).filter(([key]) => key.startsWith(`plugin.${ns}.`)).map(([key, value]) => [key.slice(`plugin.${ns}.`.length), value]));
|
|
210
|
+
if (!block) {
|
|
211
|
+
if (Object.keys(hosted).some(key => key !== 'name' && key !== 'description')) report({ level: 'error', message: 'en.json has strings for this plugin but the file has no // i18n:begin … // i18n:end block' }, file);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
let inline;
|
|
215
|
+
try { inline = JSON.parse(/const MESSAGES = ({[\s\S]*});/.exec(block)?.[1] ?? 'null'); } catch (error) { inline = null; report({ level: 'error', message: `MESSAGES is not plain JSON: ${error.message}` }, file); }
|
|
216
|
+
if (!inline?.en) { report({ level: 'error', message: 'MESSAGES.en is missing' }, file); continue; }
|
|
217
|
+
for (const [key, value] of Object.entries(inline.en)) {
|
|
218
|
+
if (hosted[key] !== value) report({ level: 'error', key: `plugin.${ns}.${key}`, message: hosted[key] === undefined ? 'missing from en.json' : 'differs from en.json' }, file);
|
|
219
|
+
}
|
|
220
|
+
for (const key of Object.keys(hosted)) {
|
|
221
|
+
if (key !== 'name' && key !== 'description' && !(key in inline.en)) report({ level: 'error', key: `plugin.${ns}.${key}`, message: 'in en.json but not in the plugin' }, file);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ---- Translations
|
|
227
|
+
const appFiles = catalogFiles(APP).filter(file => file !== 'en.json');
|
|
228
|
+
const kitFiles = new Set(catalogFiles(KIT));
|
|
229
|
+
// Tier: "supported" languages are the ones the app resolves to automatically ("Same as system");
|
|
230
|
+
// every other catalog is "community" (offered, but only when someone picks it). No list = all supported.
|
|
231
|
+
const supported = config.supported ? new Set(['en', ...config.supported]) : null;
|
|
232
|
+
const tierOf = code => (!supported || supported.has(code) ? 'supported' : 'community');
|
|
233
|
+
for (const code of supported ?? []) if (code !== 'en' && !appFiles.includes(`${code}.json`)) report({ level: 'error', message: `"supported" lists ${code}, which has no catalog` }, I18N_CONFIG_FILE);
|
|
234
|
+
const languages = [{ code: 'en', name: en.name, englishName: en.englishName, dir: 'ltr', status: 'source', tier: 'supported', reviewers: [], coverage: 1 }];
|
|
235
|
+
const table = [];
|
|
236
|
+
for (const file of appFiles) {
|
|
237
|
+
const catalog = read(join(APP, file));
|
|
238
|
+
if (!kitFiles.has(file)) report({ level: 'error', message: `no framework catalog ${label(join(KIT, file))}` }, file);
|
|
239
|
+
const kit = kitFiles.has(file) ? read(join(KIT, file)) : null;
|
|
240
|
+
const fallback = catalog.fallback ? (catalog.fallback === 'en' ? null : read(join(APP, `${catalog.fallback}.json`))) : null;
|
|
241
|
+
const cover = coverage(catalog, en.messages, fallback ?? undefined);
|
|
242
|
+
languages.push({
|
|
243
|
+
code: catalog.locale, name: catalog.name, englishName: catalog.englishName, dir: catalog.dir ?? 'ltr', status: catalog.status, tier: tierOf(catalog.locale),
|
|
244
|
+
reviewers: catalog.reviewers ?? [], ...(catalog.fallback ? { fallback: catalog.fallback } : {}), coverage: Math.round((catalog.fallback === 'en' ? 1 : cover) * 1000) / 1000,
|
|
245
|
+
});
|
|
246
|
+
if (kit && (kit.status !== catalog.status || kit.name !== catalog.name)) report({ level: 'error', message: 'name/status differ from the framework catalog of the same locale' }, file);
|
|
247
|
+
if (only.length && !only.includes(catalog.locale)) continue;
|
|
248
|
+
const shape = checkShape(catalog, file);
|
|
249
|
+
for (const issue of [...shape, ...(shape.length ? [] : checkCatalog(catalog, en.messages, meta))]) report(issue, label(join(APP, file)));
|
|
250
|
+
// The framework's words in the same language (the shell frame, the panel, the Store, the UI kit).
|
|
251
|
+
if (kit) {
|
|
252
|
+
const kitShape = checkShape(kit, file);
|
|
253
|
+
for (const issue of [...kitShape, ...(kitShape.length ? [] : checkCatalog(kit, kitEn.messages, kitMeta))]) report(issue, label(join(KIT, file)));
|
|
254
|
+
}
|
|
255
|
+
table.push(`${catalog.locale.padEnd(8)} ${catalog.status.padEnd(9)} ${(cover * 100).toFixed(1).padStart(5)}% ${catalog.englishName}`);
|
|
256
|
+
}
|
|
257
|
+
languages.sort((a, b) => (a.code === 'en' ? -1 : b.code === 'en' ? 1 : a.englishName.localeCompare(b.englishName, 'en')));
|
|
258
|
+
|
|
259
|
+
// ---- Generated files
|
|
260
|
+
const outputs = [[join(APP, 'languages.json'), `${JSON.stringify(languages, null, 2)}\n`]];
|
|
261
|
+
if (config.native) outputs.push(...renderNative(config, en, languages.map(language => (language.code === 'en' ? en : read(join(APP, `${language.code}.json`))))));
|
|
262
|
+
for (const [path, content] of outputs) {
|
|
263
|
+
let current = null;
|
|
264
|
+
try { current = readFileSync(path, 'utf8'); } catch { /* missing */ }
|
|
265
|
+
if (current === content) continue;
|
|
266
|
+
if (write) { mkdirSync(dirname(path), { recursive: true }); writeFileSync(path, content); lines.push(`wrote ${label(path)}`); }
|
|
267
|
+
else report({ level: 'error', message: 'out of date: run `waybetter i18n check --write`' }, label(path));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
lines.push(table.sort().join('\n'));
|
|
271
|
+
lines.push(`\ni18n check: ${Object.keys(en.messages).length} app + ${Object.keys(kitEn.messages).length} framework messages, ${languages.length} languages; ${errors} error(s), ${warnings} warning(s)${verbose ? '' : ' (--verbose lists them)'}.`);
|
|
272
|
+
return { errors, warnings, lines, languages };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// ---- extract ----------------------------------------------------------------------------------------
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Compares the keys the code looks up with English. Literal lookups are `t('key')`, `tx('key')`,
|
|
279
|
+
* `coreText('key')` and `i18n.t('key')` in `sources`, and `tr(app, "native.key", …)` / `trf(…)` in
|
|
280
|
+
* `nativeSources`. Keys built at runtime (`features.${id}.label`) are invisible here, so "no
|
|
281
|
+
* literal lookup" is a hint, never a reason to delete: search first.
|
|
282
|
+
*/
|
|
283
|
+
export function extractKeys(config, { onlyMissing = false } = {}) {
|
|
284
|
+
const messages = { ...read(join(config.framework, 'en.json')).messages, ...read(join(config.locales, 'en.json')).messages };
|
|
285
|
+
const used = new Map();
|
|
286
|
+
const note = (key, file) => { if (!used.has(key)) used.set(key, relative(config.root, file).replace(/\\/g, '/')); };
|
|
287
|
+
const call = /\b(?:t|tx|coreText|i18n\.t|i18n\.tx)\(\s*(['"])([a-z][A-Za-z0-9_.-]*)\1/g;
|
|
288
|
+
const native = /\btrf?\(\s*&?app,\s*"([a-z][A-Za-z0-9_.-]*)"/g;
|
|
289
|
+
for (const dir of config.sources) {
|
|
290
|
+
for (const file of walk(dir, /\.(ts|tsx|js|jsx|mjs)$/)) for (const match of readFileSync(file, 'utf8').matchAll(call)) note(match[2], file);
|
|
291
|
+
}
|
|
292
|
+
for (const dir of config.nativeSources) {
|
|
293
|
+
for (const file of walk(dir, /\.rs$/)) for (const match of readFileSync(file, 'utf8').matchAll(native)) note(match[1], file);
|
|
294
|
+
}
|
|
295
|
+
const lines = [];
|
|
296
|
+
const missing = [...used].filter(([key]) => !(key in messages));
|
|
297
|
+
for (const [key, file] of missing) lines.push(`missing ${key} (${file})`);
|
|
298
|
+
if (onlyMissing) {
|
|
299
|
+
lines.push(`${missing.length} missing`);
|
|
300
|
+
} else {
|
|
301
|
+
// The framework's own words are looked up by the framework (its tests check them).
|
|
302
|
+
const app = read(join(config.locales, 'en.json')).messages;
|
|
303
|
+
const unused = Object.keys(app).filter(key => !used.has(key) && !config.runtimeKeys.some(prefix => key.startsWith(prefix)));
|
|
304
|
+
for (const key of unused) lines.push(`no literal lookup ${key}`);
|
|
305
|
+
lines.push(`\n${used.size} keys looked up literally, ${missing.length} missing from en.json, ${unused.length} en.json keys without a literal lookup (many are built at runtime).`);
|
|
306
|
+
}
|
|
307
|
+
return { missing: missing.map(([key]) => key), lines };
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// ---- rename -----------------------------------------------------------------------------------------
|
|
311
|
+
|
|
312
|
+
const KEY = /^[a-z][A-Za-z0-9_.-]{0,127}$/;
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Renames (or, with `copy`, duplicates) keys in every catalog of the app by `map` ({ old: new }),
|
|
316
|
+
* carrying each language's own value, so a moved string is never retranslated. A catalog that lacks
|
|
317
|
+
* the old key is left as it is for that key (it falls back to English, as before). The translator
|
|
318
|
+
* notes (en.meta.json) follow. Refuses a map that would overwrite an existing English key with a
|
|
319
|
+
* different value, or that names a key English does not have.
|
|
320
|
+
*/
|
|
321
|
+
export function renameKeys(config, map, { copy = false } = {}) {
|
|
322
|
+
const entries = Object.entries(map);
|
|
323
|
+
const en = read(join(config.locales, 'en.json'));
|
|
324
|
+
for (const [from, to] of entries) {
|
|
325
|
+
if (typeof to !== 'string' || !KEY.test(from) || !KEY.test(to)) throw new I18nError(`invalid entry ${JSON.stringify(from)}: ${JSON.stringify(to)}`);
|
|
326
|
+
if (!(from in en.messages)) throw new I18nError(`${from} is not in en.json`);
|
|
327
|
+
if (to in en.messages && en.messages[to] !== en.messages[from]) throw new I18nError(`${to} already exists in en.json with another value`);
|
|
328
|
+
}
|
|
329
|
+
const lines = [];
|
|
330
|
+
const rewrite = (file, messagesOf) => {
|
|
331
|
+
const path = join(config.locales, file);
|
|
332
|
+
if (!existsSync(path)) return;
|
|
333
|
+
const raw = readFileSync(path, 'utf8');
|
|
334
|
+
const data = JSON.parse(raw);
|
|
335
|
+
const messages = messagesOf(data);
|
|
336
|
+
let changed = 0;
|
|
337
|
+
for (const [from, to] of entries) {
|
|
338
|
+
if (!(from in messages)) continue;
|
|
339
|
+
if (messages[to] !== messages[from]) { messages[to] = messages[from]; changed += 1; }
|
|
340
|
+
if (!copy && from !== to) { delete messages[from]; changed += 1; }
|
|
341
|
+
}
|
|
342
|
+
if (!changed) return;
|
|
343
|
+
writeFileSync(path, `${JSON.stringify(data, null, 2)}${raw.endsWith('\n') ? '\n' : ''}`);
|
|
344
|
+
lines.push(`${file}: ${changed} change(s)`);
|
|
345
|
+
};
|
|
346
|
+
for (const file of catalogFiles(config.locales)) rewrite(file, data => data.messages);
|
|
347
|
+
rewrite('en.meta.json', data => data);
|
|
348
|
+
lines.push(`${copy ? 'copied' : 'renamed'} ${entries.length} key(s) in ${lines.length} file(s).`);
|
|
349
|
+
return { lines };
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// ---- The command ------------------------------------------------------------------------------------
|
|
353
|
+
|
|
354
|
+
/** `waybetter i18n <check|extract|rename> …`; returns the exit code. */
|
|
355
|
+
export async function i18nCommand(args, { cwd = process.cwd(), log = console.log } = {}) {
|
|
356
|
+
const [action, ...rest] = args;
|
|
357
|
+
const flags = new Set(rest.filter(arg => arg.startsWith('--')));
|
|
358
|
+
const configAt = rest.indexOf('--config');
|
|
359
|
+
const configFile = configAt >= 0 ? rest[configAt + 1] : undefined;
|
|
360
|
+
if (configAt >= 0 && !configFile) throw new I18nError('--config needs a file');
|
|
361
|
+
const mapAt = rest.indexOf('--map');
|
|
362
|
+
const positional = rest.filter((arg, index) => !arg.startsWith('--') && (configAt < 0 || index !== configAt + 1) && (mapAt < 0 || index !== mapAt + 1));
|
|
363
|
+
if (action === 'rename') {
|
|
364
|
+
const mapFile = mapAt >= 0 ? rest[mapAt + 1] : undefined;
|
|
365
|
+
if (!mapFile) throw new I18nError('rename needs --map <file>');
|
|
366
|
+
const result = renameKeys(loadI18nConfig(cwd, configFile), read(isAbsolute(mapFile) ? mapFile : resolve(cwd, mapFile)), { copy: flags.has('--copy') });
|
|
367
|
+
for (const line of result.lines) log(line);
|
|
368
|
+
return 0;
|
|
369
|
+
}
|
|
370
|
+
if (action === 'check') {
|
|
371
|
+
const result = await checkCatalogs(loadI18nConfig(cwd, configFile), { write: flags.has('--write'), verbose: flags.has('--verbose'), only: positional });
|
|
372
|
+
for (const line of result.lines) log(line);
|
|
373
|
+
return result.errors ? 1 : 0;
|
|
374
|
+
}
|
|
375
|
+
if (action === 'extract') {
|
|
376
|
+
const result = extractKeys(loadI18nConfig(cwd, configFile), { onlyMissing: flags.has('--missing') });
|
|
377
|
+
for (const line of result.lines) log(line);
|
|
378
|
+
return result.missing.length ? 1 : 0;
|
|
379
|
+
}
|
|
380
|
+
log(I18N_USAGE);
|
|
381
|
+
return action && action !== '--help' && action !== '-h' ? 1 : 0;
|
|
382
|
+
}
|