Browse Source

Add a test scenario for localizations. Update localizations.

Add a scenario to test localizations for TextView context menu, FileDialog and Wizard.
Add localization of zh-Hans.
Add new translations for ja-JP.
Fix minor localization issues for en-US, fr-FR and ja-JP.
RoxCian 1 year ago
parent
commit
af0fed6045

+ 2 - 2
Terminal.Gui/Resources/Strings.fr-FR.resx

@@ -142,7 +142,7 @@
     <value>_Dossier</value>
   </data>
   <data name="fdFile" xml:space="preserve">
-    <value>_Ficher</value>
+    <value>Ficher</value>
   </data>
   <data name="fdSave" xml:space="preserve">
     <value>_Enregistrer</value>
@@ -151,7 +151,7 @@
     <value>E_nregistrer sous</value>
   </data>
   <data name="fdOpen" xml:space="preserve">
-    <value>_Ouvrir</value>
+    <value>Ouvrir</value>
   </data>
   <data name="fdSelectFolder" xml:space="preserve">
     <value>Sélection de _dossier</value>

+ 82 - 10
Terminal.Gui/Resources/Strings.ja-JP.resx

@@ -118,25 +118,25 @@
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <data name="ctxCopy" xml:space="preserve">
-    <value>コピー (C)</value>
+    <value>コピー (_C)</value>
   </data>
   <data name="ctxCut" xml:space="preserve">
-    <value>切り取り (T)</value>
+    <value>切り取り (_T)</value>
   </data>
   <data name="ctxDeleteAll" xml:space="preserve">
-    <value>全て削除 (D)</value>
+    <value>全て削除 (_D)</value>
   </data>
   <data name="ctxPaste" xml:space="preserve">
-    <value>貼り付け (P)</value>
+    <value>貼り付け (_P)</value>
   </data>
   <data name="ctxRedo" xml:space="preserve">
-    <value>やり直し (R)</value>
+    <value>やり直し (_R)</value>
   </data>
   <data name="ctxSelectAll" xml:space="preserve">
-    <value>全て選択 (S)</value>
+    <value>全て選択 (_S)</value>
   </data>
   <data name="ctxUndo" xml:space="preserve">
-    <value>元に戻す (U)</value>
+    <value>元に戻す (_U)</value>
   </data>
   <data name="fdDirectory" xml:space="preserve">
     <value>ディレクトリ</value>
@@ -160,12 +160,84 @@
     <value>混在選択</value>
   </data>
   <data name="wzBack" xml:space="preserve">
-    <value>戻る</value>
+    <value>戻る (_B)</value>
   </data>
   <data name="wzFinish" xml:space="preserve">
-    <value>終える</value>
+    <value>終わる (_N)</value>
   </data>
   <data name="wzNext" xml:space="preserve">
-    <value>次に</value>
+    <value>次に (_N)...</value>
+  </data>
+  <data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
+    <value>同じ名前のディレクトリはすでに存在しました</value>
+  </data>
+  <data name="fdDeleteBody" xml:space="preserve">
+    <value>“{0}”を削除もよろしいですか?この操作は元に戻りません。</value>
+  </data>
+  <data name="fdType" xml:space="preserve">
+    <value>タイプ</value>
+  </data>
+  <data name="fdSize" xml:space="preserve">
+    <value>サイズ</value>
+  </data>
+  <data name="fdPathCaption" xml:space="preserve">
+    <value>パスを入力</value>
+  </data>
+  <data name="fdFilename" xml:space="preserve">
+    <value>ファイル名</value>
+  </data>
+  <data name="fdNewTitle" xml:space="preserve">
+    <value>新規ディレクトリ</value>
+  </data>
+  <data name="fdNo" xml:space="preserve">
+    <value>いいえ</value>
+  </data>
+  <data name="fdYes" xml:space="preserve">
+    <value>はい</value>
+  </data>
+  <data name="fdModified" xml:space="preserve">
+    <value>変更日時</value>
+  </data>
+  <data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
+    <value>すでに存在したファイルまたはディレクトリを選択してください</value>
+  </data>
+  <data name="fdDirectoryMustExistFeedback" xml:space="preserve">
+    <value>すでに存在したディレクトリを選択してください</value>
+  </data>
+  <data name="fdFileMustExistFeedback" xml:space="preserve">
+    <value>すでに存在したファイルを選択してください</value>
+  </data>
+  <data name="fdRenamePrompt" xml:space="preserve">
+    <value>名前:</value>
+  </data>
+  <data name="fdDeleteTitle" xml:space="preserve">
+    <value>{0} を削除</value>
+  </data>
+  <data name="fdNewFailed" xml:space="preserve">
+    <value>新規失敗</value>
+  </data>
+  <data name="fdExisting" xml:space="preserve">
+    <value>既存</value>
+  </data>
+  <data name="fdRenameTitle" xml:space="preserve">
+    <value>名前を変更</value>
+  </data>
+  <data name="fdRenameFailedTitle" xml:space="preserve">
+    <value>変更失敗</value>
+  </data>
+  <data name="fdDeleteFailedTitle" xml:space="preserve">
+    <value>削除失敗</value>
+  </data>
+  <data name="fdFileAlreadyExistsFeedback" xml:space="preserve">
+    <value>同じ名前のファイルはすでに存在しました</value>
+  </data>
+  <data name="fdSearchCaption" xml:space="preserve">
+    <value>検索を入力</value>
+  </data>
+  <data name="fdWrongFileTypeFeedback" xml:space="preserve">
+    <value>ファイルタイプが間違っでいます</value>
+  </data>
+  <data name="fdAnyFiles" xml:space="preserve">
+    <value>任意ファイル</value>
   </data>
 </root>

+ 1 - 1
Terminal.Gui/Resources/Strings.resx

@@ -212,7 +212,7 @@
     <comment>Describes an AllowedType that matches anything</comment>
   </data>
   <data name="fdDeleteBody" xml:space="preserve">
-    <value>Are you sure you want to delete '{0}'? This operation is permanent</value>
+    <value>Are you sure you want to delete '{0}'? This operation is permanent.</value>
   </data>
   <data name="fdDeleteFailedTitle" xml:space="preserve">
     <value>Delete Failed</value>

+ 243 - 0
Terminal.Gui/Resources/Strings.zh-Hans.resx

@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="ctxSelectAll" xml:space="preserve">
+    <value>全选 (_S)</value>
+  </data>
+  <data name="ctxDeleteAll" xml:space="preserve">
+    <value>清空 (_D)</value>
+  </data>
+  <data name="ctxCopy" xml:space="preserve">
+    <value>复制 (_C)</value>
+  </data>
+  <data name="ctxCut" xml:space="preserve">
+    <value>剪切 (_T)</value>
+  </data>
+  <data name="ctxPaste" xml:space="preserve">
+    <value>粘贴 (_P)</value>
+  </data>
+  <data name="ctxUndo" xml:space="preserve">
+    <value>撤销 (_U)</value>
+  </data>
+  <data name="ctxRedo" xml:space="preserve">
+    <value>重做 (_R)</value>
+  </data>
+  <data name="fdDirectory" xml:space="preserve">
+    <value>目录</value>
+  </data>
+  <data name="fdFile" xml:space="preserve">
+    <value>文件</value>
+  </data>
+  <data name="fdSave" xml:space="preserve">
+    <value>保存</value>
+  </data>
+  <data name="fdSaveAs" xml:space="preserve">
+    <value>另存为</value>
+  </data>
+  <data name="fdOpen" xml:space="preserve">
+    <value>打开</value>
+  </data>
+  <data name="wzNext" xml:space="preserve">
+    <value>下一步 (_N)...</value>
+  </data>
+  <data name="fdSelectFolder" xml:space="preserve">
+    <value>选择文件夹</value>
+  </data>
+  <data name="fdSelectMixed" xml:space="preserve">
+    <value>混合选择</value>
+  </data>
+  <data name="wzBack" xml:space="preserve">
+    <value>返回 (_B)</value>
+  </data>
+  <data name="wzFinish" xml:space="preserve">
+    <value>结束 (_N)</value>
+  </data>
+  <data name="fdDirectoryAlreadyExistsFeedback" xml:space="preserve">
+    <value>已存在相同名称的目录</value>
+  </data>
+  <data name="fdDirectoryMustExistFeedback" xml:space="preserve">
+    <value>必须选择已有的目录</value>
+  </data>
+  <data name="fdFileAlreadyExistsFeedback" xml:space="preserve">
+    <value>已存在相同名称的文件</value>
+  </data>
+  <data name="fdFileMustExistFeedback" xml:space="preserve">
+    <value>必须选择已有的文件</value>
+  </data>
+  <data name="fdFilename" xml:space="preserve">
+    <value>文件名</value>
+  </data>
+  <data name="fdFileOrDirectoryMustExistFeedback" xml:space="preserve">
+    <value>必须选择已有的文件或目录</value>
+  </data>
+  <data name="fdModified" xml:space="preserve">
+    <value>修改时间</value>
+  </data>
+  <data name="fdPathCaption" xml:space="preserve">
+    <value>请输入路径</value>
+  </data>
+  <data name="fdSearchCaption" xml:space="preserve">
+    <value>输入以搜索</value>
+  </data>
+  <data name="fdSize" xml:space="preserve">
+    <value>大小</value>
+  </data>
+  <data name="fdType" xml:space="preserve">
+    <value>类型</value>
+  </data>
+  <data name="fdWrongFileTypeFeedback" xml:space="preserve">
+    <value>文件类型有误</value>
+  </data>
+  <data name="fdAnyFiles" xml:space="preserve">
+    <value>任意文件</value>
+  </data>
+  <data name="fdDeleteBody" xml:space="preserve">
+    <value>您是否要删除“{0}”?此操作不可撤销。</value>
+  </data>
+  <data name="fdDeleteFailedTitle" xml:space="preserve">
+    <value>删除失败</value>
+  </data>
+  <data name="fdDeleteTitle" xml:space="preserve">
+    <value>删除 {0}</value>
+  </data>
+  <data name="fdNewFailed" xml:space="preserve">
+    <value>新建失败</value>
+  </data>
+  <data name="fdNewTitle" xml:space="preserve">
+    <value>新建文件夹</value>
+  </data>
+  <data name="fdNo" xml:space="preserve">
+    <value>否</value>
+  </data>
+  <data name="fdRenameFailedTitle" xml:space="preserve">
+    <value>重命名失败</value>
+  </data>
+  <data name="fdRenamePrompt" xml:space="preserve">
+    <value>名称:</value>
+  </data>
+  <data name="fdRenameTitle" xml:space="preserve">
+    <value>重命名</value>
+  </data>
+  <data name="fdYes" xml:space="preserve">
+    <value>是</value>
+  </data>
+  <data name="fdExisting" xml:space="preserve">
+    <value>已有</value>
+  </data>
+</root>

+ 179 - 0
UICatalog/Scenarios/Localization.cs

@@ -0,0 +1,179 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios {
+	[ScenarioMetadata (Name: "Localization", Description: "Test for localization resources.")]
+	[ScenarioCategory ("Text and Formatting")]
+	[ScenarioCategory ("Tests")]
+	public class Localization : Scenario {
+		public CultureInfo CurrentCulture { get; private set; } = Thread.CurrentThread.CurrentUICulture;
+
+		private CultureInfo [] _cultureInfoSource;
+		private string [] _cultureInfoNameSource;
+		private ComboBox _languageComboBox;
+		private CheckBox _allowAnyCheckBox;
+		private OpenMode _currentOpenMode = OpenMode.File;
+
+		public override void Setup ()
+		{
+			base.Setup ();
+			_cultureInfoSource = Application.SupportedCultures.Append (CultureInfo.InvariantCulture).ToArray ();
+			_cultureInfoNameSource = Application.SupportedCultures.Select (c => $"{c.NativeName} ({c.Name})").Append ("Invariant").ToArray ();
+			var languageMenus = Application.SupportedCultures
+				.Select (c => new MenuItem ($"{c.NativeName} ({c.Name})", "", () => SetCulture (c))
+				).Concat (
+					new MenuItem [] {
+						null,
+						new MenuItem ("Invariant", "", () => SetCulture (CultureInfo.InvariantCulture))
+					}
+				)
+				.ToArray ();
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem ("_File", new MenuItem [] {
+					new MenuBarItem("_Language", languageMenus),
+					null,
+					new MenuItem ("_Quit", "", Quit),
+				}),
+			});
+			Application.Top.Add (menu);
+
+			var selectLanguageLabel = new Label ("Please select a language.") {
+				X = 2,
+				Y = 1,
+				Width = Dim.Fill (2),
+				AutoSize = true
+			};
+			Win.Add (selectLanguageLabel);
+
+			_languageComboBox = new ComboBox (_cultureInfoNameSource) {
+				X = 2,
+				Y = Pos.Bottom (selectLanguageLabel) + 1,
+				Width = _cultureInfoNameSource.Select (cn => cn.Length + 3).Max (),
+				Height = _cultureInfoNameSource.Length + 1,
+				HideDropdownListOnClick = true,
+				AutoSize = true,
+				SelectedItem = _cultureInfoNameSource.Length - 1
+			};
+			_languageComboBox.SelectedItemChanged += LanguageComboBox_SelectChanged;
+			Win.Add (_languageComboBox);
+
+			var textAndFileDialogLabel = new Label ("Right click on the text field to open a context menu, click the button to open a file dialog.\r\nOpen mode will loop through 'File', 'Directory' and 'Mixed' as 'Open' or 'Save' button clicked.") {
+				X = 2,
+				Y = Pos.Top (_languageComboBox) + 3,
+				Width = Dim.Fill (2),
+				AutoSize = true
+			};
+			Win.Add (textAndFileDialogLabel);
+
+			var textField = new TextView {
+				X = 2,
+				Y = Pos.Bottom (textAndFileDialogLabel) + 1,
+				Width = Dim.Fill (32),
+				Height = 1
+			};
+			Win.Add (textField);
+
+			_allowAnyCheckBox = new CheckBox {
+				X = Pos.Right (textField) + 1,
+				Y = Pos.Bottom (textAndFileDialogLabel) + 1,
+				Checked = false,
+				Text = "Allow any"
+			};
+			Win.Add (_allowAnyCheckBox);
+
+			var openDialogButton = new Button ("Open") {
+				X = Pos.Right (_allowAnyCheckBox) + 1,
+				Y = Pos.Bottom (textAndFileDialogLabel) + 1
+			};
+			openDialogButton.Clicked += (sender, e) => ShowFileDialog (false);
+			Win.Add (openDialogButton);
+
+			var saveDialogButton = new Button ("Save") {
+				X = Pos.Right (openDialogButton) + 1,
+				Y = Pos.Bottom (textAndFileDialogLabel) + 1
+			};
+			saveDialogButton.Clicked += (sender, e) => ShowFileDialog (true);
+			Win.Add (saveDialogButton);
+
+			var wizardLabel = new Label ("Click the button to open a wizard.") {
+				X = 2,
+				Y = Pos.Bottom (textField) + 1,
+				Width = Dim.Fill (2),
+				AutoSize = true
+			};
+			Win.Add (wizardLabel);
+
+			var wizardButton = new Button ("Open _wizard") {
+				X = 2,
+				Y = Pos.Bottom (wizardLabel) + 1
+			};
+			wizardButton.Clicked += (sender, e) => ShowWizard ();
+			Win.Add (wizardButton);
+
+			Win.Unloaded += (sender, e) => Quit ();
+		}
+
+		public void SetCulture (CultureInfo culture)
+		{
+			if (_cultureInfoSource [_languageComboBox.SelectedItem] != culture) {
+				_languageComboBox.SelectedItem = Array.IndexOf (_cultureInfoSource, culture);
+			}
+			if (this.CurrentCulture == culture) return;
+			this.CurrentCulture = culture;
+			Thread.CurrentThread.CurrentUICulture = culture;
+			Application.Refresh ();
+		}
+		private void LanguageComboBox_SelectChanged (object sender, ListViewItemEventArgs e)
+		{
+			if (e.Value is string cultureName) {
+				var item = Array.IndexOf (_cultureInfoNameSource, cultureName);
+				if (item >= 0) {
+					SetCulture (_cultureInfoSource [Array.IndexOf (_cultureInfoNameSource, cultureName)]);
+				}
+			}
+		}
+		public void ShowFileDialog (bool isSaveFile)
+		{
+			FileDialog dialog = isSaveFile ? new SaveDialog () : new OpenDialog ("", null, _currentOpenMode);
+			dialog.AllowedTypes = new List<IAllowedType> () {
+				(_allowAnyCheckBox.Checked ?? false) ? new AllowedTypeAny() : new AllowedType("Dynamic link library", ".dll"),
+				new AllowedType("Json", ".json"),
+				new AllowedType("Text", ".txt"),
+				new AllowedType("Yaml", ".yml", ".yaml")
+			};
+			dialog.MustExist = !isSaveFile;
+			dialog.AllowsMultipleSelection = !isSaveFile;
+			_currentOpenMode++;
+			if (_currentOpenMode > OpenMode.Mixed) _currentOpenMode = OpenMode.File;
+			Application.Run (dialog);
+		}
+		public void ShowWizard ()
+		{
+			Wizard wizard = new Wizard {
+				Height = 8,
+				Width = 36,
+				Title = "The wizard"
+			};
+			wizard.AddStep (new WizardStep () {
+				HelpText = "Wizard first step",
+			});
+			wizard.AddStep (new WizardStep () {
+				HelpText = "Wizard step 2",
+				NextButtonText = ">>> (_N)"
+			});
+			wizard.AddStep (new WizardStep () {
+				HelpText = "Wizard last step"
+			});
+			Application.Run (wizard);
+		}
+		public void Quit ()
+		{
+			SetCulture (CultureInfo.InvariantCulture);
+			Application.RequestStop ();
+		}
+	}
+}