From c79de21e558ff6af44ee007f6a3b8391dd31edb6 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:04:26 +0200 Subject: [PATCH 01/10] Revert initializr template zip modifications --- .../com/codename1/initializr/Initializr.java | 58 +++++++++++++- .../initializr/model/GeneratorModel.java | 76 +++++++++++++++++++ .../initializr/model/ProjectOptions.java | 39 +++++++++- .../initializr/ui/TemplatePreviewPanel.java | 36 ++++++++- .../src/main/resources/messages.properties | 7 ++ .../src/main/resources/messages_ar.properties | 8 ++ .../src/main/resources/messages_de.properties | 7 ++ .../src/main/resources/messages_es.properties | 7 ++ .../src/main/resources/messages_fr.properties | 7 ++ .../src/main/resources/messages_he.properties | 8 ++ .../src/main/resources/messages_it.properties | 7 ++ .../src/main/resources/messages_ja.properties | 7 ++ .../src/main/resources/messages_ko.properties | 7 ++ .../src/main/resources/messages_nl.properties | 7 ++ .../src/main/resources/messages_pt.properties | 7 ++ .../main/resources/messages_zh_CN.properties | 7 ++ .../model/GeneratorModelMatrixTest.java | 16 ++++ 17 files changed, 304 insertions(+), 7 deletions(-) create mode 100644 scripts/initializr/common/src/main/resources/messages.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_ar.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_de.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_es.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_fr.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_he.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_it.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_ja.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_ko.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_nl.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_pt.properties create mode 100644 scripts/initializr/common/src/main/resources/messages_zh_CN.properties diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/Initializr.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/Initializr.java index 0c9e460a5a..710203a2f6 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/Initializr.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/Initializr.java @@ -15,6 +15,7 @@ import com.codename1.ui.Button; import com.codename1.ui.ButtonGroup; import com.codename1.ui.CheckBox; +import com.codename1.ui.spinner.Picker; import com.codename1.ui.Component; import com.codename1.ui.Container; import com.codename1.ui.Dialog; @@ -47,6 +48,8 @@ public void runApp() { final ProjectOptions.ThemeMode[] selectedThemeMode = new ProjectOptions.ThemeMode[]{ProjectOptions.ThemeMode.LIGHT}; final ProjectOptions.Accent[] selectedAccent = new ProjectOptions.Accent[]{ProjectOptions.Accent.DEFAULT}; final boolean[] roundedButtons = new boolean[]{true}; + final boolean[] includeLocalizationBundles = new boolean[]{true}; + final ProjectOptions.PreviewLanguage[] previewLanguage = new ProjectOptions.PreviewLanguage[]{ProjectOptions.PreviewLanguage.ENGLISH}; final RadioButton[] templateButtons = new RadioButton[Template.values().length]; final SpanLabel summaryLabel = new SpanLabel(); final TemplatePreviewPanel previewPanel = new TemplatePreviewPanel(selectedTemplate[0]); @@ -64,7 +67,10 @@ public void runApp() { final Runnable refresh = new Runnable() { public void run() { - ProjectOptions options = new ProjectOptions(selectedThemeMode[0], selectedAccent[0], roundedButtons[0]); + ProjectOptions options = new ProjectOptions( + selectedThemeMode[0], selectedAccent[0], roundedButtons[0], + includeLocalizationBundles[0], previewLanguage[0] + ); previewPanel.setTemplate(selectedTemplate[0]); previewPanel.setOptions(options); boolean canCustomizeTheme = supportsLivePreview(selectedTemplate[0]); @@ -92,12 +98,14 @@ public void run() { ); final Container idePanel = createIdeSelectorPanel(selectedIde, refresh); final Container themePanel = createThemeOptionsPanel(selectedThemeMode, selectedAccent, roundedButtons, refresh); + final Container localizationPanel = createLocalizationPanel(includeLocalizationBundles, previewLanguage, refresh); themePanelRef[0] = themePanel; final Container settingsPanel = BoxLayout.encloseY(summaryLabel); Accordion advancedAccordion = new Accordion(); advancedAccordion.addContent("IDE", idePanel); advancedAccordion.addContent("Theme Customization", themePanel); + advancedAccordion.addContent("Localization", localizationPanel); advancedAccordion.addContent("Current Settings", settingsPanel); advancedAccordion.setAutoClose(false); advancedAccordion.setScrollable(false); @@ -123,7 +131,10 @@ public void run() { } String appName = appNameField.getText() == null ? "" : appNameField.getText().trim(); String packageName = packageField.getText() == null ? "" : packageField.getText().trim(); - ProjectOptions options = new ProjectOptions(selectedThemeMode[0], selectedAccent[0], roundedButtons[0]); + ProjectOptions options = new ProjectOptions( + selectedThemeMode[0], selectedAccent[0], roundedButtons[0], + includeLocalizationBundles[0], previewLanguage[0] + ); GeneratorModel.create(selectedIde[0], selectedTemplate[0], appName, packageName, options).generate(); }); @@ -141,6 +152,37 @@ public void run() { form.show(); } + private Container createLocalizationPanel(boolean[] includeLocalizationBundles, + ProjectOptions.PreviewLanguage[] previewLanguage, + Runnable onSelectionChanged) { + CheckBox includeBundles = new CheckBox("Include Resource Bundles"); + includeBundles.setUIID("InitializrChoice"); + includeBundles.setSelected(includeLocalizationBundles[0]); + + Picker languagePicker = new Picker(); + languagePicker.setUIID("InitializrField"); + String[] labels = new String[ProjectOptions.PreviewLanguage.values().length]; + for (int i = 0; i < labels.length; i++) { + labels[i] = ProjectOptions.PreviewLanguage.values()[i].label; + } + languagePicker.setStrings(labels); + languagePicker.setSelectedString(previewLanguage[0].label); + + includeBundles.addActionListener(e -> { + includeLocalizationBundles[0] = includeBundles.isSelected(); + languagePicker.setEnabled(includeBundles.isSelected()); + onSelectionChanged.run(); + }); + languagePicker.setEnabled(includeBundles.isSelected()); + languagePicker.addActionListener(e -> { + String selected = languagePicker.getSelectedString(); + previewLanguage[0] = findLanguageByLabel(selected); + onSelectionChanged.run(); + }); + + return BoxLayout.encloseY(includeBundles, labeledField("Preview Language", languagePicker)); + } + private Container createHeader() { Label title = new Label("Initializr - Scaffold a Project in Seconds"); title.setUIID("InitializrHeroTitle"); @@ -319,6 +361,16 @@ private Container labeledFieldWithHelp(String label, Component input, String hel return BoxLayout.encloseY(header, input); } + + private ProjectOptions.PreviewLanguage findLanguageByLabel(String label) { + for (ProjectOptions.PreviewLanguage language : ProjectOptions.PreviewLanguage.values()) { + if (language.label.equals(label)) { + return language; + } + } + return ProjectOptions.PreviewLanguage.ENGLISH; + } + private String formatEnumLabel(String text) { if ("DEFAULT".equals(text)) { return "Clean"; @@ -445,6 +497,8 @@ private String createSummary(String appName, String packageName, Template templa + "Theme: " + options.themeMode.name() + "\n" + "Accent: " + options.accent.name() + "\n" + "Rounded Buttons: " + (options.roundedButtons ? "Yes" : "No") + "\n" + + "Localization Bundles: " + (options.includeLocalizationBundles ? "Yes" : "No") + "\n" + + "Preview Language: " + options.previewLanguage.label + "\n" + "Kotlin: " + (template.IS_KOTLIN ? "Yes" : "No"); } diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/model/GeneratorModel.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/model/GeneratorModel.java index a618f0c61c..e555b41095 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/model/GeneratorModel.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/model/GeneratorModel.java @@ -73,6 +73,7 @@ void writeProjectZip(OutputStream outputStream) throws IOException { } copyZipEntriesToMap(template.CSS, mergedEntries, ZipEntryType.TEMPLATE_CSS); copyZipEntriesToMap(template.SOURCE_ZIP, mergedEntries, ZipEntryType.TEMPLATE_SOURCE); + addLocalizationEntries(mergedEntries); try (ZipOutputStream zos = new ZipOutputStream(outputStream)) { for (Map.Entry fileEntry : mergedEntries.entrySet()) { @@ -84,6 +85,30 @@ void writeProjectZip(OutputStream outputStream) throws IOException { } } + + private void addLocalizationEntries(Map mergedEntries) throws IOException { + if (!isBareTemplate() || !options.includeLocalizationBundles) { + return; + } + copySingleTextEntryToMap( + "common/src/main/resources/messages.properties", + readResourceToString("/messages.properties"), + mergedEntries, + ZipEntryType.COMMON + ); + for (ProjectOptions.PreviewLanguage language : ProjectOptions.PreviewLanguage.values()) { + if (language == ProjectOptions.PreviewLanguage.ENGLISH) { + continue; + } + copySingleTextEntryToMap( + "common/src/main/resources/messages_" + language.bundleSuffix + ".properties", + readResourceToString("/messages_" + language.bundleSuffix + ".properties"), + mergedEntries, + ZipEntryType.COMMON + ); + } + } + private void copyZipEntriesToMap(String zipResource, Map mergedEntries, ZipEntryType zipType) throws IOException { try(ZipInputStream zis = new ZipInputStream(getResourceAsStream(zipResource))) { ZipEntry entry = zis.getNextEntry(); @@ -155,6 +180,9 @@ private byte[] applyDataReplacements(String targetPath, byte[] sourceData) throw if ("common/codenameone_settings.properties".equals(targetPath)) { content = replaceProperty(content, "codename1.kotlin", String.valueOf(template.IS_KOTLIN)); } + if (options.includeLocalizationBundles && isBareTemplate()) { + content = injectLocalizationBootstrap(targetPath, content); + } if (isBareTemplate() && "common/src/main/css/theme.css".equals(targetPath)) { content += buildThemeOverrides(); } @@ -167,6 +195,54 @@ private byte[] applyDataReplacements(String targetPath, byte[] sourceData) throw return content.getBytes("UTF-8"); } + + private String injectLocalizationBootstrap(String targetPath, String content) { + String javaMainPath = "common/src/main/java/" + packageName.replace('.', '/') + "/" + appName + ".java"; + String kotlinMainPath = "common/src/main/kotlin/" + packageName.replace('.', '/') + "/" + appName + ".kt"; + if (javaMainPath.equals(targetPath)) { + return injectJavaLocalizationBootstrap(content); + } + if (kotlinMainPath.equals(targetPath)) { + return injectKotlinLocalizationBootstrap(content); + } + return content; + } + + private String injectJavaLocalizationBootstrap(String content) { + if (content.indexOf("setBundle(") >= 0) { + return content; + } + content = StringUtil.replaceAll(content, "import static com.codename1.ui.CN.*;\n", "import static com.codename1.ui.CN.*;\nimport com.codename1.l10n.L10NManager;\nimport com.codename1.ui.plaf.UIManager;\nimport java.util.Hashtable;\n"); + String method = "\n @Override\n" + + " public void init(Object context) {\n" + + " String language = L10NManager.getInstance().getLanguage();\n" + + " Hashtable bundle = Resources.getGlobalResources().getL10N(\"messages\", language);\n" + + " UIManager.getInstance().setBundle(bundle);\n" + + " }\n\n"; + int firstBrace = content.indexOf('{'); + if (firstBrace > -1) { + return content.substring(0, firstBrace + 1) + method + content.substring(firstBrace + 1); + } + return content; + } + + private String injectKotlinLocalizationBootstrap(String content) { + if (content.indexOf("setBundle(") >= 0) { + return content; + } + content = StringUtil.replaceAll(content, "import com.codename1.system.Lifecycle\n", "import com.codename1.system.Lifecycle\nimport com.codename1.l10n.L10NManager\nimport com.codename1.ui.plaf.UIManager\nimport com.codename1.ui.util.Resources\nimport java.util.Hashtable\n"); + String method = "\n override fun init(context: Any?) {\n" + + " val language = L10NManager.getInstance().language\n" + + " val bundle: Hashtable? = Resources.getGlobalResources().getL10N(\"messages\", language)\n" + + " UIManager.getInstance().setBundle(bundle)\n" + + " }\n\n"; + int firstBrace = content.indexOf('{'); + if (firstBrace > -1) { + return content.substring(0, firstBrace + 1) + method + content.substring(firstBrace + 1); + } + return content; + } + private static String replaceTagValue(String xml, String tagName, String value) { String open = "<" + tagName + ">"; String close = ""; diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/model/ProjectOptions.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/model/ProjectOptions.java index c3f9351d53..7595fa1fc3 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/model/ProjectOptions.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/model/ProjectOptions.java @@ -1,6 +1,36 @@ package com.codename1.initializr.model; public final class ProjectOptions { + public enum PreviewLanguage { + ENGLISH("English", "en", false), + FRENCH("Fran\u00e7ais", "fr", false), + GERMAN("Deutsch", "de", false), + SPANISH("Espa\u00f1ol", "es", false), + ITALIAN("Italiano", "it", false), + PORTUGUESE("Portugu\u00eas", "pt", false), + DUTCH("Nederlands", "nl", false), + CHINESE_SIMPLIFIED("\u4e2d\u6587 (\u7b80\u4f53)", "zh_CN", false), + JAPANESE("\u65e5\u672c\u8a9e", "ja", false), + KOREAN("\ud55c\uad6d\uc5b4", "ko", false), + ARABIC("\u0627\u0644\u0639\u0631\u0628\u064a\u0629", "ar", true), + HEBREW("\u05e2\u05d1\u05e8\u05d9\u05ea", "he", true); + + public final String label; + public final String bundleSuffix; + public final boolean rtl; + + PreviewLanguage(String label, String bundleSuffix, boolean rtl) { + this.label = label; + this.bundleSuffix = bundleSuffix; + this.rtl = rtl; + } + + @Override + public String toString() { + return label; + } + } + public enum ThemeMode { LIGHT, DARK @@ -16,14 +46,19 @@ public enum Accent { public final ThemeMode themeMode; public final Accent accent; public final boolean roundedButtons; + public final boolean includeLocalizationBundles; + public final PreviewLanguage previewLanguage; - public ProjectOptions(ThemeMode themeMode, Accent accent, boolean roundedButtons) { + public ProjectOptions(ThemeMode themeMode, Accent accent, boolean roundedButtons, + boolean includeLocalizationBundles, PreviewLanguage previewLanguage) { this.themeMode = themeMode; this.accent = accent; this.roundedButtons = roundedButtons; + this.includeLocalizationBundles = includeLocalizationBundles; + this.previewLanguage = previewLanguage == null ? PreviewLanguage.ENGLISH : previewLanguage; } public static ProjectOptions defaults() { - return new ProjectOptions(ThemeMode.LIGHT, Accent.DEFAULT, true); + return new ProjectOptions(ThemeMode.LIGHT, Accent.DEFAULT, true, true, PreviewLanguage.ENGLISH); } } diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java index d8e50fb28d..51a913a796 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java @@ -1,7 +1,7 @@ package com.codename1.initializr.ui; -import com.codename1.components.ToastBar; import com.codename1.components.ImageViewer; +import com.codename1.components.ToastBar; import com.codename1.initializr.model.ProjectOptions; import com.codename1.initializr.model.Template; import com.codename1.ui.Button; @@ -11,13 +11,15 @@ import com.codename1.ui.Dialog; import com.codename1.ui.FontImage; import com.codename1.ui.Form; -import com.codename1.ui.Image; import com.codename1.ui.InterFormContainer; import com.codename1.ui.Label; import com.codename1.ui.layouts.BorderLayout; import com.codename1.ui.layouts.BoxLayout; +import com.codename1.ui.plaf.UIManager; import com.codename1.ui.util.Resources; +import java.util.Hashtable; + public class TemplatePreviewPanel { private final Container root; private final Container previewHolder; @@ -59,18 +61,46 @@ public void setOptions(ProjectOptions options) { } private Form createBarebonesPreviewForm(ProjectOptions options) { + installBundle(options); Form form = new Form("Hi World", BoxLayout.y()); Button helloButton = new Button("Hello World"); helloButton.setUIID("Button"); helloButton.addActionListener(e -> Dialog.show("Hello Codename One", "Welcome to Codename One", "OK", null)); form.add(helloButton); - Command menuCommand = form.getToolbar().addMaterialCommandToLeftBar("", FontImage.MATERIAL_MENU, e -> + Command menuCommand = form.getToolbar().addMaterialCommandToSideMenu("Hello Command", + FontImage.MATERIAL_CHECK, 4, e -> Dialog.show("Hello Codename One", "Welcome to Codename One", "OK", null)); + form.getToolbar().addMaterialCommandToLeftBar("", FontImage.MATERIAL_MENU, e -> ToastBar.showInfoMessage("Side menu is not available in embedded preview mode.")); Button menuButton = form.getToolbar().findCommandComponent(menuCommand); applyLivePreviewOptions(form, helloButton, menuButton, options); return form; } + private void installBundle(ProjectOptions options) { + if (!options.includeLocalizationBundles) { + UIManager.getInstance().setBundle(null); + return; + } + Hashtable bundle = findBundle(options.previewLanguage); + UIManager.getInstance().setBundle(bundle); + } + + private Hashtable findBundle(ProjectOptions.PreviewLanguage language) { + Resources resources = Resources.getGlobalResources(); + if (resources == null || language == null) { + return null; + } + Hashtable exact = resources.getL10N("messages", language.bundleSuffix); + if (exact != null) { + return exact; + } + int split = language.bundleSuffix.indexOf('_'); + if (split > 0) { + return resources.getL10N("messages", language.bundleSuffix.substring(0, split)); + } + return null; + } + private void updateMode() { previewHolder.removeAll(); if (template == Template.BAREBONES || template == Template.KOTLIN) { diff --git a/scripts/initializr/common/src/main/resources/messages.properties b/scripts/initializr/common/src/main/resources/messages.properties new file mode 100644 index 0000000000..5e93db9304 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages.properties @@ -0,0 +1,7 @@ +app.title=Hi World +button.hello=Hello World +command.hello=Hello Command +dialog.title=Hello Codename One +dialog.message=Welcome to Codename One +dialog.ok=OK +preview.menu.unavailable=Side menu is not available in embedded preview mode. diff --git a/scripts/initializr/common/src/main/resources/messages_ar.properties b/scripts/initializr/common/src/main/resources/messages_ar.properties new file mode 100644 index 0000000000..9d7796b628 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_ar.properties @@ -0,0 +1,8 @@ +@rtl=true +app.title=مرحبا بالعالم +button.hello=مرحبا بالعالم +command.hello=أمر الترحيب +dialog.title=مرحبًا Codename One +dialog.message=مرحبًا بك في Codename One +dialog.ok=موافق +preview.menu.unavailable=القائمة الجانبية غير متاحة في المعاينة المضمنة. diff --git a/scripts/initializr/common/src/main/resources/messages_de.properties b/scripts/initializr/common/src/main/resources/messages_de.properties new file mode 100644 index 0000000000..765a4ac676 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_de.properties @@ -0,0 +1,7 @@ +app.title=Hallo Welt +button.hello=Hallo Welt +command.hello=Hallo-Befehl +dialog.title=Hallo Codename One +dialog.message=Willkommen bei Codename One +dialog.ok=OK +preview.menu.unavailable=Das Seitenmenü ist in der eingebetteten Vorschau nicht verfügbar. diff --git a/scripts/initializr/common/src/main/resources/messages_es.properties b/scripts/initializr/common/src/main/resources/messages_es.properties new file mode 100644 index 0000000000..cff840a6e2 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_es.properties @@ -0,0 +1,7 @@ +app.title=Hola Mundo +button.hello=Hola Mundo +command.hello=Comando Hola +dialog.title=Hola Codename One +dialog.message=Bienvenido a Codename One +dialog.ok=Aceptar +preview.menu.unavailable=El menú lateral no está disponible en el modo de vista previa incrustada. diff --git a/scripts/initializr/common/src/main/resources/messages_fr.properties b/scripts/initializr/common/src/main/resources/messages_fr.properties new file mode 100644 index 0000000000..f7313039ec --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_fr.properties @@ -0,0 +1,7 @@ +app.title=Bonjour le monde +button.hello=Bonjour le monde +command.hello=Commande Bonjour +dialog.title=Bonjour Codename One +dialog.message=Bienvenue dans Codename One +dialog.ok=OK +preview.menu.unavailable=Le menu latéral n'est pas disponible en mode aperçu intégré. diff --git a/scripts/initializr/common/src/main/resources/messages_he.properties b/scripts/initializr/common/src/main/resources/messages_he.properties new file mode 100644 index 0000000000..2ca9281b67 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_he.properties @@ -0,0 +1,8 @@ +@rtl=true +app.title=שלום עולם +button.hello=שלום עולם +command.hello=פקודת שלום +dialog.title=שלום Codename One +dialog.message=ברוכים הבאים ל-Codename One +dialog.ok=אישור +preview.menu.unavailable=תפריט הצד לא זמין במצב תצוגה מקדימה מוטמע. diff --git a/scripts/initializr/common/src/main/resources/messages_it.properties b/scripts/initializr/common/src/main/resources/messages_it.properties new file mode 100644 index 0000000000..6b923b3702 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_it.properties @@ -0,0 +1,7 @@ +app.title=Ciao Mondo +button.hello=Ciao Mondo +command.hello=Comando Ciao +dialog.title=Ciao Codename One +dialog.message=Benvenuto in Codename One +dialog.ok=OK +preview.menu.unavailable=Il menu laterale non è disponibile nella modalità anteprima incorporata. diff --git a/scripts/initializr/common/src/main/resources/messages_ja.properties b/scripts/initializr/common/src/main/resources/messages_ja.properties new file mode 100644 index 0000000000..22c3a17b83 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_ja.properties @@ -0,0 +1,7 @@ +app.title=こんにちは世界 +button.hello=こんにちは世界 +command.hello=挨拶コマンド +dialog.title=こんにちは Codename One +dialog.message=Codename Oneへようこそ +dialog.ok=OK +preview.menu.unavailable=埋め込みプレビューではサイドメニューを利用できません。 diff --git a/scripts/initializr/common/src/main/resources/messages_ko.properties b/scripts/initializr/common/src/main/resources/messages_ko.properties new file mode 100644 index 0000000000..368280d4f8 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_ko.properties @@ -0,0 +1,7 @@ +app.title=안녕하세요 세계 +button.hello=안녕하세요 세계 +command.hello=인사 명령 +dialog.title=안녕하세요 Codename One +dialog.message=Codename One에 오신 것을 환영합니다 +dialog.ok=확인 +preview.menu.unavailable=임베디드 미리보기에서는 사이드 메뉴를 사용할 수 없습니다. diff --git a/scripts/initializr/common/src/main/resources/messages_nl.properties b/scripts/initializr/common/src/main/resources/messages_nl.properties new file mode 100644 index 0000000000..80323d0057 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_nl.properties @@ -0,0 +1,7 @@ +app.title=Hallo Wereld +button.hello=Hallo Wereld +command.hello=Hallo-opdracht +dialog.title=Hallo Codename One +dialog.message=Welkom bij Codename One +dialog.ok=OK +preview.menu.unavailable=Het zijmenu is niet beschikbaar in ingesloten voorbeeldmodus. diff --git a/scripts/initializr/common/src/main/resources/messages_pt.properties b/scripts/initializr/common/src/main/resources/messages_pt.properties new file mode 100644 index 0000000000..b1373546ae --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_pt.properties @@ -0,0 +1,7 @@ +app.title=Olá Mundo +button.hello=Olá Mundo +command.hello=Comando Olá +dialog.title=Olá Codename One +dialog.message=Bem-vindo ao Codename One +dialog.ok=OK +preview.menu.unavailable=O menu lateral não está disponível no modo de pré-visualização incorporado. diff --git a/scripts/initializr/common/src/main/resources/messages_zh_CN.properties b/scripts/initializr/common/src/main/resources/messages_zh_CN.properties new file mode 100644 index 0000000000..6e9c746ab0 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_zh_CN.properties @@ -0,0 +1,7 @@ +app.title=你好,世界 +button.hello=你好,世界 +command.hello=问候命令 +dialog.title=你好 Codename One +dialog.message=欢迎使用 Codename One +dialog.ok=确定 +preview.menu.unavailable=嵌入式预览模式下侧边菜单不可用。 diff --git a/scripts/initializr/common/src/test/java/com/codename1/initializr/model/GeneratorModelMatrixTest.java b/scripts/initializr/common/src/test/java/com/codename1/initializr/model/GeneratorModelMatrixTest.java index a15128c5ff..df6d831423 100644 --- a/scripts/initializr/common/src/test/java/com/codename1/initializr/model/GeneratorModelMatrixTest.java +++ b/scripts/initializr/common/src/test/java/com/codename1/initializr/model/GeneratorModelMatrixTest.java @@ -37,6 +37,7 @@ private void validateCombination(Template template, IDE ide) throws Exception { assertCommonPom(entries, template, packageName, mainClassName); assertSettings(entries, template, packageName, mainClassName); assertMainSourceFile(entries, template, packageName, mainClassName); + assertLocalizationBundles(entries, template); assertNoTemplatePlaceholders(entries, template); } @@ -135,6 +136,10 @@ private void assertMainSourceFile(Map entries, Template template String mainSource = getText(entries, path); assertContains(mainSource, "package " + packageName, "Main source package was not refactored"); assertContains(mainSource, mainClassName, "Main source class was not renamed"); + if (template == Template.BAREBONES || template == Template.KOTLIN) { + assertContains(mainSource, "setBundle", "Barebones starter should install localization bundle"); + assertContains(mainSource, "messages", "Barebones starter should load i18n messages properties"); + } if (template == Template.GRUB) { String grubModel = getText(entries, "common/src/main/java/" + packagePath + "/models/AccountModel.java"); assertContains(grubModel, "extends Entity", "Grub models should keep CodeRAD 1 Entity base class"); @@ -146,6 +151,17 @@ private void assertMainSourceFile(Map entries, Template template } } + + private void assertLocalizationBundles(Map entries, Template template) { + if (template == Template.BAREBONES || template == Template.KOTLIN) { + assertNotNull(entries.get("common/src/main/resources/messages.properties"), "Barebones templates should include default localization bundle"); + assertNotNull(entries.get("common/src/main/resources/messages_ar.properties"), "Barebones templates should include Arabic localization bundle"); + assertNotNull(entries.get("common/src/main/resources/messages_he.properties"), "Barebones templates should include Hebrew localization bundle"); + return; + } + assertNull(entries.get("common/src/main/resources/messages.properties"), "Non-bare templates should not receive default localization bundle"); + } + private void assertNoTemplatePlaceholders(Map entries, Template template) { for (String path : entries.keySet()) { assertFalse(path.indexOf("com/example/myapp") >= 0, "Unrefactored placeholder path found: " + path); From a7c37ca49623d1ba63159fc17edd76108ceb3b71 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:18:34 +0200 Subject: [PATCH 02/10] Guard Initializr preview bundle lookup against missing L10N --- .../initializr/ui/TemplatePreviewPanel.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java index 51a913a796..a8b660dcb2 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java @@ -90,13 +90,17 @@ private Hashtable findBundle(ProjectOptions.PreviewLanguage lang if (resources == null || language == null) { return null; } - Hashtable exact = resources.getL10N("messages", language.bundleSuffix); - if (exact != null) { - return exact; - } - int split = language.bundleSuffix.indexOf('_'); - if (split > 0) { - return resources.getL10N("messages", language.bundleSuffix.substring(0, split)); + try { + Hashtable exact = resources.getL10N("messages", language.bundleSuffix); + if (exact != null) { + return exact; + } + int split = language.bundleSuffix.indexOf('_'); + if (split > 0) { + return resources.getL10N("messages", language.bundleSuffix.substring(0, split)); + } + } catch (RuntimeException ignored) { + // L10N bundle may be unavailable in current resource set. } return null; } From 4cbb5d176f2a82cf34d2fb18f4e53fb75ce7aa50 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:47:15 +0200 Subject: [PATCH 03/10] Adjust preview form refresh and remove extra menu command --- .../initializr/ui/TemplatePreviewPanel.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java index a8b660dcb2..930435aa8d 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java @@ -1,11 +1,9 @@ package com.codename1.initializr.ui; import com.codename1.components.ImageViewer; -import com.codename1.components.ToastBar; import com.codename1.initializr.model.ProjectOptions; import com.codename1.initializr.model.Template; import com.codename1.ui.Button; -import com.codename1.ui.Command; import com.codename1.ui.Component; import com.codename1.ui.Container; import com.codename1.ui.Dialog; @@ -20,6 +18,8 @@ import java.util.Hashtable; +import static com.codename1.ui.CN.getCurrentForm; + public class TemplatePreviewPanel { private final Container root; private final Container previewHolder; @@ -67,12 +67,9 @@ private Form createBarebonesPreviewForm(ProjectOptions options) { helloButton.setUIID("Button"); helloButton.addActionListener(e -> Dialog.show("Hello Codename One", "Welcome to Codename One", "OK", null)); form.add(helloButton); - Command menuCommand = form.getToolbar().addMaterialCommandToSideMenu("Hello Command", + form.getToolbar().addMaterialCommandToSideMenu("Hello Command", FontImage.MATERIAL_CHECK, 4, e -> Dialog.show("Hello Codename One", "Welcome to Codename One", "OK", null)); - form.getToolbar().addMaterialCommandToLeftBar("", FontImage.MATERIAL_MENU, e -> - ToastBar.showInfoMessage("Side menu is not available in embedded preview mode.")); - Button menuButton = form.getToolbar().findCommandComponent(menuCommand); - applyLivePreviewOptions(form, helloButton, menuButton, options); + applyLivePreviewOptions(form, helloButton, null, options); return form; } @@ -109,6 +106,11 @@ private void updateMode() { previewHolder.removeAll(); if (template == Template.BAREBONES || template == Template.KOTLIN) { Form liveForm = createBarebonesPreviewForm(options); + Form current = getCurrentForm(); + liveForm.show(); + if (current != null && current != liveForm) { + current.showBack(); + } liveFormPreview = new InterFormContainer(liveForm); liveFormPreview.setUIID("InitializrLiveFrame"); previewHolder.add(BorderLayout.CENTER, liveFormPreview); From edfe6d3ca73498ea6870b67af1078677818738d4 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:47:21 +0200 Subject: [PATCH 04/10] Recreate preview form without show/showBack indirection --- .../com/codename1/initializr/ui/TemplatePreviewPanel.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java index 930435aa8d..4c1652b587 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java @@ -18,7 +18,6 @@ import java.util.Hashtable; -import static com.codename1.ui.CN.getCurrentForm; public class TemplatePreviewPanel { private final Container root; @@ -106,11 +105,6 @@ private void updateMode() { previewHolder.removeAll(); if (template == Template.BAREBONES || template == Template.KOTLIN) { Form liveForm = createBarebonesPreviewForm(options); - Form current = getCurrentForm(); - liveForm.show(); - if (current != null && current != liveForm) { - current.showBack(); - } liveFormPreview = new InterFormContainer(liveForm); liveFormPreview.setUIID("InitializrLiveFrame"); previewHolder.add(BorderLayout.CENTER, liveFormPreview); From e31df61485755ff286aa0c5437a2e0601cb070fe Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 18:02:39 +0200 Subject: [PATCH 05/10] Show newly recreated preview form on language picker selection --- .../java/com/codename1/initializr/Initializr.java | 6 ++++-- .../initializr/ui/TemplatePreviewPanel.java | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/Initializr.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/Initializr.java index 710203a2f6..538dedf47e 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/Initializr.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/Initializr.java @@ -98,7 +98,7 @@ public void run() { ); final Container idePanel = createIdeSelectorPanel(selectedIde, refresh); final Container themePanel = createThemeOptionsPanel(selectedThemeMode, selectedAccent, roundedButtons, refresh); - final Container localizationPanel = createLocalizationPanel(includeLocalizationBundles, previewLanguage, refresh); + final Container localizationPanel = createLocalizationPanel(includeLocalizationBundles, previewLanguage, refresh, previewPanel); themePanelRef[0] = themePanel; final Container settingsPanel = BoxLayout.encloseY(summaryLabel); @@ -154,7 +154,8 @@ public void run() { private Container createLocalizationPanel(boolean[] includeLocalizationBundles, ProjectOptions.PreviewLanguage[] previewLanguage, - Runnable onSelectionChanged) { + Runnable onSelectionChanged, + TemplatePreviewPanel previewPanel) { CheckBox includeBundles = new CheckBox("Include Resource Bundles"); includeBundles.setUIID("InitializrChoice"); includeBundles.setSelected(includeLocalizationBundles[0]); @@ -178,6 +179,7 @@ private Container createLocalizationPanel(boolean[] includeLocalizationBundles, String selected = languagePicker.getSelectedString(); previewLanguage[0] = findLanguageByLabel(selected); onSelectionChanged.run(); + previewPanel.showUpdatedLivePreview(); }); return BoxLayout.encloseY(includeBundles, labeledField("Preview Language", languagePicker)); diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java index 4c1652b587..07e91dd6b6 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java @@ -59,6 +59,18 @@ public void setOptions(ProjectOptions options) { updateMode(); } + public void showUpdatedLivePreview() { + if (template == Template.BAREBONES || template == Template.KOTLIN) { + Form liveForm = createBarebonesPreviewForm(options); + liveForm.show(); + liveFormPreview = new InterFormContainer(liveForm); + liveFormPreview.setUIID("InitializrLiveFrame"); + previewHolder.removeAll(); + previewHolder.add(BorderLayout.CENTER, liveFormPreview); + previewHolder.revalidate(); + } + } + private Form createBarebonesPreviewForm(ProjectOptions options) { installBundle(options); Form form = new Form("Hi World", BoxLayout.y()); From 501b499229b823e18f52259bcc3c8f4ccb633355 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 18:13:14 +0200 Subject: [PATCH 06/10] Replace preview form in container without showing separate form --- .../java/com/codename1/initializr/ui/TemplatePreviewPanel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java index 07e91dd6b6..35e1278aa7 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java @@ -62,7 +62,6 @@ public void setOptions(ProjectOptions options) { public void showUpdatedLivePreview() { if (template == Template.BAREBONES || template == Template.KOTLIN) { Form liveForm = createBarebonesPreviewForm(options); - liveForm.show(); liveFormPreview = new InterFormContainer(liveForm); liveFormPreview.setUIID("InitializrLiveFrame"); previewHolder.removeAll(); From 20cb917fb672955736b998db0014f2ac4029f876 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 18:24:46 +0200 Subject: [PATCH 07/10] Use literal UI text keys in Initializr localization bundles --- .../common/src/main/resources/messages.properties | 14 +++++++------- .../src/main/resources/messages_ar.properties | 14 +++++++------- .../src/main/resources/messages_de.properties | 14 +++++++------- .../src/main/resources/messages_es.properties | 14 +++++++------- .../src/main/resources/messages_fr.properties | 14 +++++++------- .../src/main/resources/messages_he.properties | 14 +++++++------- .../src/main/resources/messages_it.properties | 14 +++++++------- .../src/main/resources/messages_ja.properties | 14 +++++++------- .../src/main/resources/messages_ko.properties | 14 +++++++------- .../src/main/resources/messages_nl.properties | 14 +++++++------- .../src/main/resources/messages_pt.properties | 14 +++++++------- .../src/main/resources/messages_zh_CN.properties | 14 +++++++------- 12 files changed, 84 insertions(+), 84 deletions(-) diff --git a/scripts/initializr/common/src/main/resources/messages.properties b/scripts/initializr/common/src/main/resources/messages.properties index 5e93db9304..4f24396858 100644 --- a/scripts/initializr/common/src/main/resources/messages.properties +++ b/scripts/initializr/common/src/main/resources/messages.properties @@ -1,7 +1,7 @@ -app.title=Hi World -button.hello=Hello World -command.hello=Hello Command -dialog.title=Hello Codename One -dialog.message=Welcome to Codename One -dialog.ok=OK -preview.menu.unavailable=Side menu is not available in embedded preview mode. +Hi\ World=Hi World +Hello\ World=Hello World +Hello\ Command=Hello Command +Hello\ Codename\ One=Hello Codename One +Welcome\ to\ Codename\ One=Welcome to Codename One +OK=OK +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=Side menu is not available in embedded preview mode. diff --git a/scripts/initializr/common/src/main/resources/messages_ar.properties b/scripts/initializr/common/src/main/resources/messages_ar.properties index 9d7796b628..764a117f2e 100644 --- a/scripts/initializr/common/src/main/resources/messages_ar.properties +++ b/scripts/initializr/common/src/main/resources/messages_ar.properties @@ -1,8 +1,8 @@ @rtl=true -app.title=مرحبا بالعالم -button.hello=مرحبا بالعالم -command.hello=أمر الترحيب -dialog.title=مرحبًا Codename One -dialog.message=مرحبًا بك في Codename One -dialog.ok=موافق -preview.menu.unavailable=القائمة الجانبية غير متاحة في المعاينة المضمنة. +Hi\ World=مرحبا بالعالم +Hello\ World=مرحبا بالعالم +Hello\ Command=أمر الترحيب +Hello\ Codename\ One=مرحبًا Codename One +Welcome\ to\ Codename\ One=مرحبًا بك في Codename One +OK=موافق +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=القائمة الجانبية غير متاحة في المعاينة المضمنة. diff --git a/scripts/initializr/common/src/main/resources/messages_de.properties b/scripts/initializr/common/src/main/resources/messages_de.properties index 765a4ac676..8e1fe6a6bd 100644 --- a/scripts/initializr/common/src/main/resources/messages_de.properties +++ b/scripts/initializr/common/src/main/resources/messages_de.properties @@ -1,7 +1,7 @@ -app.title=Hallo Welt -button.hello=Hallo Welt -command.hello=Hallo-Befehl -dialog.title=Hallo Codename One -dialog.message=Willkommen bei Codename One -dialog.ok=OK -preview.menu.unavailable=Das Seitenmenü ist in der eingebetteten Vorschau nicht verfügbar. +Hi\ World=Hallo Welt +Hello\ World=Hallo Welt +Hello\ Command=Hallo-Befehl +Hello\ Codename\ One=Hallo Codename One +Welcome\ to\ Codename\ One=Willkommen bei Codename One +OK=OK +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=Das Seitenmenü ist in der eingebetteten Vorschau nicht verfügbar. diff --git a/scripts/initializr/common/src/main/resources/messages_es.properties b/scripts/initializr/common/src/main/resources/messages_es.properties index cff840a6e2..d1e9a6a4b7 100644 --- a/scripts/initializr/common/src/main/resources/messages_es.properties +++ b/scripts/initializr/common/src/main/resources/messages_es.properties @@ -1,7 +1,7 @@ -app.title=Hola Mundo -button.hello=Hola Mundo -command.hello=Comando Hola -dialog.title=Hola Codename One -dialog.message=Bienvenido a Codename One -dialog.ok=Aceptar -preview.menu.unavailable=El menú lateral no está disponible en el modo de vista previa incrustada. +Hi\ World=Hola Mundo +Hello\ World=Hola Mundo +Hello\ Command=Comando Hola +Hello\ Codename\ One=Hola Codename One +Welcome\ to\ Codename\ One=Bienvenido a Codename One +OK=Aceptar +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=El menú lateral no está disponible en el modo de vista previa incrustada. diff --git a/scripts/initializr/common/src/main/resources/messages_fr.properties b/scripts/initializr/common/src/main/resources/messages_fr.properties index f7313039ec..4277cf51f0 100644 --- a/scripts/initializr/common/src/main/resources/messages_fr.properties +++ b/scripts/initializr/common/src/main/resources/messages_fr.properties @@ -1,7 +1,7 @@ -app.title=Bonjour le monde -button.hello=Bonjour le monde -command.hello=Commande Bonjour -dialog.title=Bonjour Codename One -dialog.message=Bienvenue dans Codename One -dialog.ok=OK -preview.menu.unavailable=Le menu latéral n'est pas disponible en mode aperçu intégré. +Hi\ World=Bonjour le monde +Hello\ World=Bonjour le monde +Hello\ Command=Commande Bonjour +Hello\ Codename\ One=Bonjour Codename One +Welcome\ to\ Codename\ One=Bienvenue dans Codename One +OK=OK +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=Le menu latéral n'est pas disponible en mode aperçu intégré. diff --git a/scripts/initializr/common/src/main/resources/messages_he.properties b/scripts/initializr/common/src/main/resources/messages_he.properties index 2ca9281b67..6ef3a4a9b9 100644 --- a/scripts/initializr/common/src/main/resources/messages_he.properties +++ b/scripts/initializr/common/src/main/resources/messages_he.properties @@ -1,8 +1,8 @@ @rtl=true -app.title=שלום עולם -button.hello=שלום עולם -command.hello=פקודת שלום -dialog.title=שלום Codename One -dialog.message=ברוכים הבאים ל-Codename One -dialog.ok=אישור -preview.menu.unavailable=תפריט הצד לא זמין במצב תצוגה מקדימה מוטמע. +Hi\ World=שלום עולם +Hello\ World=שלום עולם +Hello\ Command=פקודת שלום +Hello\ Codename\ One=שלום Codename One +Welcome\ to\ Codename\ One=ברוכים הבאים ל-Codename One +OK=אישור +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=תפריט הצד לא זמין במצב תצוגה מקדימה מוטמע. diff --git a/scripts/initializr/common/src/main/resources/messages_it.properties b/scripts/initializr/common/src/main/resources/messages_it.properties index 6b923b3702..fa2b26835c 100644 --- a/scripts/initializr/common/src/main/resources/messages_it.properties +++ b/scripts/initializr/common/src/main/resources/messages_it.properties @@ -1,7 +1,7 @@ -app.title=Ciao Mondo -button.hello=Ciao Mondo -command.hello=Comando Ciao -dialog.title=Ciao Codename One -dialog.message=Benvenuto in Codename One -dialog.ok=OK -preview.menu.unavailable=Il menu laterale non è disponibile nella modalità anteprima incorporata. +Hi\ World=Ciao Mondo +Hello\ World=Ciao Mondo +Hello\ Command=Comando Ciao +Hello\ Codename\ One=Ciao Codename One +Welcome\ to\ Codename\ One=Benvenuto in Codename One +OK=OK +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=Il menu laterale non è disponibile nella modalità anteprima incorporata. diff --git a/scripts/initializr/common/src/main/resources/messages_ja.properties b/scripts/initializr/common/src/main/resources/messages_ja.properties index 22c3a17b83..4dc228115f 100644 --- a/scripts/initializr/common/src/main/resources/messages_ja.properties +++ b/scripts/initializr/common/src/main/resources/messages_ja.properties @@ -1,7 +1,7 @@ -app.title=こんにちは世界 -button.hello=こんにちは世界 -command.hello=挨拶コマンド -dialog.title=こんにちは Codename One -dialog.message=Codename Oneへようこそ -dialog.ok=OK -preview.menu.unavailable=埋め込みプレビューではサイドメニューを利用できません。 +Hi\ World=こんにちは世界 +Hello\ World=こんにちは世界 +Hello\ Command=挨拶コマンド +Hello\ Codename\ One=こんにちは Codename One +Welcome\ to\ Codename\ One=Codename Oneへようこそ +OK=OK +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=埋め込みプレビューではサイドメニューを利用できません。 diff --git a/scripts/initializr/common/src/main/resources/messages_ko.properties b/scripts/initializr/common/src/main/resources/messages_ko.properties index 368280d4f8..d4a22b6eb7 100644 --- a/scripts/initializr/common/src/main/resources/messages_ko.properties +++ b/scripts/initializr/common/src/main/resources/messages_ko.properties @@ -1,7 +1,7 @@ -app.title=안녕하세요 세계 -button.hello=안녕하세요 세계 -command.hello=인사 명령 -dialog.title=안녕하세요 Codename One -dialog.message=Codename One에 오신 것을 환영합니다 -dialog.ok=확인 -preview.menu.unavailable=임베디드 미리보기에서는 사이드 메뉴를 사용할 수 없습니다. +Hi\ World=안녕하세요 세계 +Hello\ World=안녕하세요 세계 +Hello\ Command=인사 명령 +Hello\ Codename\ One=안녕하세요 Codename One +Welcome\ to\ Codename\ One=Codename One에 오신 것을 환영합니다 +OK=확인 +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=임베디드 미리보기에서는 사이드 메뉴를 사용할 수 없습니다. diff --git a/scripts/initializr/common/src/main/resources/messages_nl.properties b/scripts/initializr/common/src/main/resources/messages_nl.properties index 80323d0057..549d678403 100644 --- a/scripts/initializr/common/src/main/resources/messages_nl.properties +++ b/scripts/initializr/common/src/main/resources/messages_nl.properties @@ -1,7 +1,7 @@ -app.title=Hallo Wereld -button.hello=Hallo Wereld -command.hello=Hallo-opdracht -dialog.title=Hallo Codename One -dialog.message=Welkom bij Codename One -dialog.ok=OK -preview.menu.unavailable=Het zijmenu is niet beschikbaar in ingesloten voorbeeldmodus. +Hi\ World=Hallo Wereld +Hello\ World=Hallo Wereld +Hello\ Command=Hallo-opdracht +Hello\ Codename\ One=Hallo Codename One +Welcome\ to\ Codename\ One=Welkom bij Codename One +OK=OK +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=Het zijmenu is niet beschikbaar in ingesloten voorbeeldmodus. diff --git a/scripts/initializr/common/src/main/resources/messages_pt.properties b/scripts/initializr/common/src/main/resources/messages_pt.properties index b1373546ae..76a3a3e53f 100644 --- a/scripts/initializr/common/src/main/resources/messages_pt.properties +++ b/scripts/initializr/common/src/main/resources/messages_pt.properties @@ -1,7 +1,7 @@ -app.title=Olá Mundo -button.hello=Olá Mundo -command.hello=Comando Olá -dialog.title=Olá Codename One -dialog.message=Bem-vindo ao Codename One -dialog.ok=OK -preview.menu.unavailable=O menu lateral não está disponível no modo de pré-visualização incorporado. +Hi\ World=Olá Mundo +Hello\ World=Olá Mundo +Hello\ Command=Comando Olá +Hello\ Codename\ One=Olá Codename One +Welcome\ to\ Codename\ One=Bem-vindo ao Codename One +OK=OK +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=O menu lateral não está disponível no modo de pré-visualização incorporado. diff --git a/scripts/initializr/common/src/main/resources/messages_zh_CN.properties b/scripts/initializr/common/src/main/resources/messages_zh_CN.properties index 6e9c746ab0..281c557008 100644 --- a/scripts/initializr/common/src/main/resources/messages_zh_CN.properties +++ b/scripts/initializr/common/src/main/resources/messages_zh_CN.properties @@ -1,7 +1,7 @@ -app.title=你好,世界 -button.hello=你好,世界 -command.hello=问候命令 -dialog.title=你好 Codename One -dialog.message=欢迎使用 Codename One -dialog.ok=确定 -preview.menu.unavailable=嵌入式预览模式下侧边菜单不可用。 +Hi\ World=你好,世界 +Hello\ World=你好,世界 +Hello\ Command=问候命令 +Hello\ Codename\ One=你好 Codename One +Welcome\ to\ Codename\ One=欢迎使用 Codename One +OK=确定 +Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=嵌入式预览模式下侧边菜单不可用。 From 96db5dbf4af667d800ee5b0dff27c95b7e8e2813 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 19:22:25 +0200 Subject: [PATCH 08/10] Improve preview bundle loading fallback for language refresh --- .../initializr/ui/TemplatePreviewPanel.java | 61 +++++++++++++++---- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java index 35e1278aa7..647e1ebdc6 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/ui/TemplatePreviewPanel.java @@ -3,6 +3,8 @@ import com.codename1.components.ImageViewer; import com.codename1.initializr.model.ProjectOptions; import com.codename1.initializr.model.Template; +import com.codename1.io.Log; +import com.codename1.io.Properties; import com.codename1.ui.Button; import com.codename1.ui.Component; import com.codename1.ui.Container; @@ -16,8 +18,10 @@ import com.codename1.ui.plaf.UIManager; import com.codename1.ui.util.Resources; +import java.io.InputStream; import java.util.Hashtable; +import static com.codename1.ui.CN.getResourceAsStream; public class TemplatePreviewPanel { private final Container root; @@ -93,25 +97,60 @@ private void installBundle(ProjectOptions options) { } private Hashtable findBundle(ProjectOptions.PreviewLanguage language) { - Resources resources = Resources.getGlobalResources(); - if (resources == null || language == null) { + if (language == null) { return null; } - try { - Hashtable exact = resources.getL10N("messages", language.bundleSuffix); - if (exact != null) { - return exact; + Resources resources = Resources.getGlobalResources(); + if (resources != null) { + try { + Hashtable exact = resources.getL10N("messages", language.bundleSuffix); + if (exact != null) { + return exact; + } + int split = language.bundleSuffix.indexOf('_'); + if (split > 0) { + Hashtable languageOnly = resources.getL10N("messages", language.bundleSuffix.substring(0, split)); + if (languageOnly != null) { + return languageOnly; + } + } + } catch (RuntimeException err) { + Log.e(err); } - int split = language.bundleSuffix.indexOf('_'); - if (split > 0) { - return resources.getL10N("messages", language.bundleSuffix.substring(0, split)); + } + + String[] candidates = language.bundleSuffix.indexOf('_') > 0 + ? new String[]{"/messages_" + language.bundleSuffix + ".properties", "/messages_" + language.bundleSuffix.substring(0, language.bundleSuffix.indexOf('_')) + ".properties", "/messages.properties"} + : new String[]{"/messages_" + language.bundleSuffix + ".properties", "/messages.properties"}; + + for (String path : candidates) { + Hashtable loaded = loadBundleProperties(path); + if (loaded != null) { + return loaded; } - } catch (RuntimeException ignored) { - // L10N bundle may be unavailable in current resource set. } return null; } + private Hashtable loadBundleProperties(String resourcePath) { + try (InputStream input = getResourceAsStream(resourcePath)) { + if (input == null) { + return null; + } + Properties props = new Properties(); + props.load(input); + Hashtable out = new Hashtable(); + for (Object key : props.keySet()) { + String keyString = key.toString(); + out.put(keyString, props.getProperty(keyString)); + } + return out; + } catch (Exception err) { + Log.e(err); + return null; + } + } + private void updateMode() { previewHolder.removeAll(); if (template == Template.BAREBONES || template == Template.KOTLIN) { From 03cce4e09d35d7a23ff3e4eab3483777ae78465d Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 19:43:59 +0200 Subject: [PATCH 09/10] Translate Codename One text in RTL bundles to avoid mixed-direction inversion --- .../common/src/main/resources/messages_ar.properties | 4 ++-- .../common/src/main/resources/messages_he.properties | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/initializr/common/src/main/resources/messages_ar.properties b/scripts/initializr/common/src/main/resources/messages_ar.properties index 764a117f2e..1a073b345b 100644 --- a/scripts/initializr/common/src/main/resources/messages_ar.properties +++ b/scripts/initializr/common/src/main/resources/messages_ar.properties @@ -2,7 +2,7 @@ Hi\ World=مرحبا بالعالم Hello\ World=مرحبا بالعالم Hello\ Command=أمر الترحيب -Hello\ Codename\ One=مرحبًا Codename One -Welcome\ to\ Codename\ One=مرحبًا بك في Codename One +Hello\ Codename\ One=مرحبًا كودنيم ون +Welcome\ to\ Codename\ One=مرحبًا بك في كودنيم ون OK=موافق Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=القائمة الجانبية غير متاحة في المعاينة المضمنة. diff --git a/scripts/initializr/common/src/main/resources/messages_he.properties b/scripts/initializr/common/src/main/resources/messages_he.properties index 6ef3a4a9b9..0f3edefaf1 100644 --- a/scripts/initializr/common/src/main/resources/messages_he.properties +++ b/scripts/initializr/common/src/main/resources/messages_he.properties @@ -2,7 +2,7 @@ Hi\ World=שלום עולם Hello\ World=שלום עולם Hello\ Command=פקודת שלום -Hello\ Codename\ One=שלום Codename One -Welcome\ to\ Codename\ One=ברוכים הבאים ל-Codename One +Hello\ Codename\ One=שלום קודניימ וואן +Welcome\ to\ Codename\ One=ברוכים הבאים לקודניימ וואן OK=אישור Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=תפריט הצד לא זמין במצב תצוגה מקדימה מוטמע. From 307312ab50e403782a3c42679847bd44910b27a9 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 26 Feb 2026 20:06:48 +0200 Subject: [PATCH 10/10] Fix Hebrew Codename One transliteration in localization bundle --- .../common/src/main/resources/messages_he.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/initializr/common/src/main/resources/messages_he.properties b/scripts/initializr/common/src/main/resources/messages_he.properties index 0f3edefaf1..e89af5e3f0 100644 --- a/scripts/initializr/common/src/main/resources/messages_he.properties +++ b/scripts/initializr/common/src/main/resources/messages_he.properties @@ -2,7 +2,7 @@ Hi\ World=שלום עולם Hello\ World=שלום עולם Hello\ Command=פקודת שלום -Hello\ Codename\ One=שלום קודניימ וואן -Welcome\ to\ Codename\ One=ברוכים הבאים לקודניימ וואן +Hello\ Codename\ One=שלום קודניים וואן +Welcome\ to\ Codename\ One=ברוכים הבאים לקודניים וואן OK=אישור Side\ menu\ is\ not\ available\ in\ embedded\ preview\ mode.=תפריט הצד לא זמין במצב תצוגה מקדימה מוטמע.