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..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 @@ -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, previewPanel); 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,39 @@ public void run() { form.show(); } + private Container createLocalizationPanel(boolean[] includeLocalizationBundles, + ProjectOptions.PreviewLanguage[] previewLanguage, + Runnable onSelectionChanged, + TemplatePreviewPanel previewPanel) { + 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(); + previewPanel.showUpdatedLivePreview(); + }); + + 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 +363,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 +499,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..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 @@ -1,23 +1,28 @@ package com.codename1.initializr.ui; -import com.codename1.components.ToastBar; 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.Command; import com.codename1.ui.Component; import com.codename1.ui.Container; 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.io.InputStream; +import java.util.Hashtable; + +import static com.codename1.ui.CN.getResourceAsStream; + public class TemplatePreviewPanel { private final Container root; private final Container previewHolder; @@ -58,19 +63,94 @@ public void setOptions(ProjectOptions options) { updateMode(); } + public void showUpdatedLivePreview() { + if (template == Template.BAREBONES || template == Template.KOTLIN) { + Form liveForm = createBarebonesPreviewForm(options); + 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()); 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 -> - ToastBar.showInfoMessage("Side menu is not available in embedded preview mode.")); - Button menuButton = form.getToolbar().findCommandComponent(menuCommand); - applyLivePreviewOptions(form, helloButton, menuButton, options); + form.getToolbar().addMaterialCommandToSideMenu("Hello Command", + FontImage.MATERIAL_CHECK, 4, e -> Dialog.show("Hello Codename One", "Welcome to Codename One", "OK", null)); + applyLivePreviewOptions(form, helloButton, null, 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) { + if (language == null) { + return null; + } + 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); + } + } + + 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; + } + } + 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) { 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..4f24396858 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages.properties @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..1a073b345b --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_ar.properties @@ -0,0 +1,8 @@ +@rtl=true +Hi\ World=مرحبا بالعالم +Hello\ World=مرحبا بالعالم +Hello\ Command=أمر الترحيب +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_de.properties b/scripts/initializr/common/src/main/resources/messages_de.properties new file mode 100644 index 0000000000..8e1fe6a6bd --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_de.properties @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..d1e9a6a4b7 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_es.properties @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..4277cf51f0 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_fr.properties @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..e89af5e3f0 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_he.properties @@ -0,0 +1,8 @@ +@rtl=true +Hi\ World=שלום עולם +Hello\ World=שלום עולם +Hello\ Command=פקודת שלום +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_it.properties b/scripts/initializr/common/src/main/resources/messages_it.properties new file mode 100644 index 0000000000..fa2b26835c --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_it.properties @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..4dc228115f --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_ja.properties @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..d4a22b6eb7 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_ko.properties @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..549d678403 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_nl.properties @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..76a3a3e53f --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_pt.properties @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..281c557008 --- /dev/null +++ b/scripts/initializr/common/src/main/resources/messages_zh_CN.properties @@ -0,0 +1,7 @@ +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/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);