From 0a1bb6edef7d40898194afb4da149a73981e29e9 Mon Sep 17 00:00:00 2001 From: Louis Pontoise Date: Wed, 6 May 2020 04:17:15 +0900 Subject: [PATCH] feat: add arabic localization --- alt-tab-macos.xcodeproj/project.pbxproj | 33 +++ resources/l10n/ar.lproj/InfoPlist.strings | 2 + resources/l10n/ar.lproj/Localizable.strings | 210 ++++++++++++++++++ .../generic-components/text/TextField.swift | 12 +- 4 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 resources/l10n/ar.lproj/InfoPlist.strings create mode 100644 resources/l10n/ar.lproj/Localizable.strings diff --git a/alt-tab-macos.xcodeproj/project.pbxproj b/alt-tab-macos.xcodeproj/project.pbxproj index fb11c731..a3136323 100644 --- a/alt-tab-macos.xcodeproj/project.pbxproj +++ b/alt-tab-macos.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ D04BA1B133D53572D7B312C2 /* ThumbnailFontIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA1DF8CAB2FAB7FE9244B /* ThumbnailFontIconView.swift */; }; D04BA1C85041FB043FD43E65 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BA05006D56C7AA011C0CE /* Localizable.strings */; }; D04BA1CEC6B9C8945FEC8740 /* ThumbnailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA258B56193958D60978A /* ThumbnailView.swift */; }; + D04BA22840D40E3885B2B29E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BA3A932D3C8F850504919 /* InfoPlist.strings */; }; D04BA26A691D56031FCCF00C /* Sysctl.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA8DB8AA7E5570DAC568A /* Sysctl.swift */; }; D04BA276B3241D440F65B149 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BA5C2BB394F1624DD5B45 /* InfoPlist.strings */; }; D04BA2A6FF9DDDC5A1A68E36 /* Applications.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA282BB16C1554595A968 /* Applications.swift */; }; @@ -60,6 +61,7 @@ D04BA9B7A964C5FABFEB9DA2 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BA053A0E0157E817B2E04 /* Localizable.strings */; }; D04BA9D63A88AF2C20A1E656 /* SF-Pro-Text-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = D04BA60A6D08C041F5BF8CC9 /* SF-Pro-Text-Regular.otf */; }; D04BAAAF5CFA991D3B078DB8 /* KeyboardEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA4A621A8A15660F973C1 /* KeyboardEvents.swift */; }; + D04BAAB5C4E78AE375EA7D3C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BAA56B4EEAF17F767C7FD /* Localizable.strings */; }; D04BAABE804F3769CE22BEB6 /* HyperlinkLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA49E45BFFF3D9FC60E43 /* HyperlinkLabel.swift */; }; D04BAADED6FE28D42924AEBF /* PrivateApis.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA5C401AFA55CC67C7188 /* PrivateApis.swift */; }; D04BAAF7ACC3B361FBBF52AA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BAED4D420C506DAF539F1 /* Localizable.strings */; }; @@ -164,6 +166,7 @@ D04BA7C6F2519091717F4B4E /* SystemPermissions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemPermissions.swift; sourceTree = ""; }; D04BA7C836A8CE8C0B8D128B /* TextArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextArea.swift; sourceTree = ""; }; D04BA7CF9C2D1BEC7C05AB24 /* Spaces.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spaces.swift; sourceTree = ""; }; + D04BA7F8F1F44D5D9844BFF5 /* ar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ar; path = InfoPlist.strings; sourceTree = ""; }; D04BA81B25C166EFB3223639 /* extract_l10n_strings.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = extract_l10n_strings.sh; sourceTree = ""; }; D04BA8209A337A2960716E3B /* zh-CN */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = Localizable.strings; sourceTree = ""; }; D04BA82F792DF53958D92572 /* AltTab.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AltTab.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -192,6 +195,7 @@ D04BABBB124EAA6D4CC389F6 /* it */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = it; path = Localizable.strings; sourceTree = ""; }; D04BABDC2286BBE3D63E4A33 /* CONTRIBUTING.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CONTRIBUTING.md; sourceTree = ""; }; D04BAC02D60EF22D9CC7D969 /* commitlint.config.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = commitlint.config.js; sourceTree = ""; }; + D04BAC08AEDFBF722D613801 /* ar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ar; path = Localizable.strings; sourceTree = ""; }; D04BAC159731F80FDAF4EA6C /* 1-row.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "1-row.jpg"; sourceTree = ""; }; D04BAC2FF99F629CD4ED20FC /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; D04BAC34CFD42A7F6F1F01C0 /* CGWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGWindow.swift; sourceTree = ""; }; @@ -551,6 +555,15 @@ path = hu.lproj; sourceTree = ""; }; + D04BA90F4F92BE2E7EDFDF7E /* ar.lproj */ = { + isa = PBXGroup; + children = ( + D04BA3A932D3C8F850504919 /* InfoPlist.strings */, + D04BAA56B4EEAF17F767C7FD /* Localizable.strings */, + ); + path = ar.lproj; + sourceTree = ""; + }; D04BA9CA03317B315B267E21 /* resources */ = { isa = PBXGroup; children = ( @@ -657,6 +670,7 @@ D04BA5CE8B0F0D131BC609F1 /* zh-CN.lproj */, D04BA575A23CE769CD038CDA /* pt-BR.lproj */, D04BAB35FC157A6EF34EC038 /* ru.lproj */, + D04BA90F4F92BE2E7EDFDF7E /* ar.lproj */, ); path = l10n; sourceTree = ""; @@ -742,6 +756,7 @@ "zh-CN", "pt-BR", ru, + ar, ); mainGroup = D04BA1463D2A17038222BB84; productRefGroup = D04BA1A461BBB5A9BE15E015 /* Products */; @@ -790,6 +805,8 @@ D04BA83AF2B1C3C5166C119F /* InfoPlist.strings in Resources */, D04BABD613F88C27E720F316 /* InfoPlist.strings in Resources */, D04BA0182F4734A5C8BB63DC /* Localizable.strings in Resources */, + D04BA22840D40E3885B2B29E /* InfoPlist.strings in Resources */, + D04BAAB5C4E78AE375EA7D3C /* Localizable.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -977,6 +994,14 @@ name = InfoPlist.strings; sourceTree = ""; }; + D04BA3A932D3C8F850504919 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + D04BA7F8F1F44D5D9844BFF5 /* ar */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; D04BA3B51D05213404938366 /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( @@ -1081,6 +1106,14 @@ name = InfoPlist.strings; sourceTree = ""; }; + D04BAA56B4EEAF17F767C7FD /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + D04BAC08AEDFBF722D613801 /* ar */, + ); + name = Localizable.strings; + sourceTree = ""; + }; D04BAAEC2847830A3991F8D1 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( diff --git a/resources/l10n/ar.lproj/InfoPlist.strings b/resources/l10n/ar.lproj/InfoPlist.strings new file mode 100644 index 00000000..dd89cff9 --- /dev/null +++ b/resources/l10n/ar.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/*Copyright (human-readable)*/ +"NSHumanReadableCopyright" = "رخصة GPL-3.0"; diff --git a/resources/l10n/ar.lproj/Localizable.strings b/resources/l10n/ar.lproj/Localizable.strings new file mode 100644 index 00000000..4728dedb --- /dev/null +++ b/resources/l10n/ar.lproj/Localizable.strings @@ -0,0 +1,210 @@ + +/*No comment provided by engineer.*/ +"❖ Windows 10" = "❖ Windows 10"; + +/*No comment provided by engineer.*/ +"About" = "حول"; + +/*No comment provided by engineer.*/ +"Acknowledgments" = "شكر وتقدير"; + +/*No comment provided by engineer.*/ +"Active app" = "البرنامج الحالي"; + +/*No comment provided by engineer.*/ +"Active screen" = "الشاشة الحالية"; + +/*No comment provided by engineer.*/ +"Active space" = "المساحة الحالية"; + +/*No comment provided by engineer.*/ +"Align windows:" = "ترتيب النوافذ:"; + +/*No comment provided by engineer.*/ +"All apps" = "كل البرامج"; + +/*No comment provided by engineer.*/ +"All screens" = "كل الشاشات"; + +/*No comment provided by engineer.*/ +"All spaces" = "كل المساحات"; + +/*No comment provided by engineer.*/ +"Apparition delay:" = "تأخر الوموض:"; + +/*No comment provided by engineer.*/ +"Appearance" = "المظهر"; + +/*No comment provided by engineer.*/ +"Are you sure you don’t want a response?" = "هل أنت متأكد بأنك لا تريد رداً ؟"; + +/*No comment provided by engineer.*/ +"Arrow keys" = "أزرار الأسهم"; + +/*No comment provided by engineer.*/ +"Auto-install updates periodically" = "تثبيت التحديثات بشكل دوري تلقائي"; + +/*Cancel button*/ +"Cancel" = "إلغاء"; + +/*No comment provided by engineer.*/ +"Cancel and hide" = "إلغاء وإخفاء"; + +/*No comment provided by engineer.*/ +"Center" = "توسيط"; + +/*No comment provided by engineer.*/ +"Check for updates now…" = "البحث عن تحديثات الآن…"; + +/*No comment provided by engineer.*/ +"Check for updates periodically" = "ابحث عن تحديثات بشكل دوري"; + +/*No comment provided by engineer.*/ +"Check for updates…" = "ابحث عن تحديثات…"; + +/*No comment provided by engineer.*/ +"Close window" = "إغلاق النافذة"; + +/*No comment provided by engineer.*/ +"Don’t check for updates periodically" = "لا تبحث عن تحديثات بشكل دوري"; + +/*No comment provided by engineer.*/ +"General" = "عام"; + +/*No comment provided by engineer.*/ +"Hidden" = "مخفي"; + +/*No comment provided by engineer.*/ +"Hide space number labels:" = "إخفاء مساحة الأرقام:"; + +/*No comment provided by engineer.*/ +"Hide/Show app" = "إخفاء/إظهار برنامج"; + +/*No comment provided by engineer.*/ +"Hold" = "ثبّت"; + +/*No comment provided by engineer.*/ +"I think the app could be improved with…" = "اعتقد أنه بالإمكان تطوير البرنامج بـ…"; + +/*No comment provided by engineer.*/ +"Latest releases" = "آخر الإصدارات"; + +/*No comment provided by engineer.*/ +"Left" = "يسار"; + +/*No comment provided by engineer.*/ +"Max size on screen:" = "أكبر حجم على الشاشة:"; + +/*No comment provided by engineer.*/ +"Max windows per row:" = "الحد الأعلى للنوافذ للصف:"; + +/*No comment provided by engineer.*/ +"Min windows per row:" = "الحد الأدنى للنوافذ للصف:"; + +/*No comment provided by engineer.*/ +"Minimize/Deminimize window" = "تصغير/تكبير نافذة"; + +/*No comment provided by engineer.*/ +"Minimized" = "مصغّر"; + +/*No comment provided by engineer.*/ +"Mouse hover" = "تمرير المؤشر"; + +/*Copyright (human-readable)*/ +"NSHumanReadableCopyright" = "رخصة GPL-3.0"; + +/*No comment provided by engineer.*/ +"Optional: email (if you want a reply)" = "اختياري: بريد (إذا كنت تريد رد)"; + +/*No comment provided by engineer.*/ +"Preferences…" = "التفضيلات…"; + +/*No comment provided by engineer.*/ +"Quit %@" = "خروج %@"; + +/*No comment provided by engineer.*/ +"Quit app" = "إغلاق البرنامج"; + +/*No comment provided by engineer.*/ +"Rows of windows:" = "صفوف النوافذ:"; + +/*No comment provided by engineer.*/ +"Screen including menu bar" = "شاشة شريط القوائم"; + +/*No comment provided by engineer.*/ +"Screen including mouse" = "شاشة المؤشر"; + +/*No comment provided by engineer.*/ +"Screen showing AltTab" = "شاشة الـAltTab"; + +/*No comment provided by engineer.*/ +"Select next window" = "حدد النافذة التالية"; + +/*No comment provided by engineer.*/ +"Select previous window" = "حدد النافذة السابقة"; + +/*No comment provided by engineer.*/ +"Select windows using:" = "حدد النوافذ التي تستخدم:"; + +/*No comment provided by engineer.*/ +"Send" = "إرسال"; + +/*No comment provided by engineer.*/ +"Send anyway" = "إرسال على أية حال"; + +/*No comment provided by engineer.*/ +"Send debug profile (CPU, memory, etc)" = "إرسال ملف الأخطاء (معالج، ذاكرة، إلخ)"; + +/*No comment provided by engineer.*/ +"Send feedback" = "أرسل رأيك"; + +/*No comment provided by engineer.*/ +"Send feedback…" = "أرسل رأيك…"; + +/*No comment provided by engineer.*/ +"Share improvement ideas, or report bugs" = "شارك أفكارك التطويرية، أو بلغ عن أخطاء"; + +/*No comment provided by engineer.*/ +"Show" = "إظهار"; + +/*No comment provided by engineer.*/ +"Show on:" = "أظهر على:"; + +/*No comment provided by engineer.*/ +"Show the following windows:" = "حدد النوافذ التالية:"; + +/*No comment provided by engineer.*/ +"Source code repository" = "مخزن شفرة المصدر"; + +/*No comment provided by engineer.*/ +"Start at login:" = "شغّل البرنامج عند الدخول:"; + +/*No comment provided by engineer.*/ +"Theme:" = "المظهر:"; + +/*No comment provided by engineer.*/ +"then press:" = "واضغط:"; + +/*No comment provided by engineer.*/ +"Updates" = "تحديثات"; + +/*No comment provided by engineer.*/ +"Updates policy:" = "سياسة التحديثات:"; + +/*No comment provided by engineer.*/ +"Version" = "الإصدار"; + +/*No comment provided by engineer.*/ +"View existing discussions" = "أنظر للنقاشات الحالية"; + +/*No comment provided by engineer.*/ +"Window app icon size:" = "حجم أيقونة النافذة:"; + +/*No comment provided by engineer.*/ +"Window title font size:" = "حجم خط عنوان النافذة:"; + +/*No comment provided by engineer.*/ +"You didn’t write your email, thus can’t receive any response." = "لم تكتب بريدك؛ فلذلك لن تحصل على رد."; + +/*No comment provided by engineer.*/ +" macOS" = " macOS"; diff --git a/src/ui/generic-components/text/TextField.swift b/src/ui/generic-components/text/TextField.swift index 099b1d81..5908ab9c 100644 --- a/src/ui/generic-components/text/TextField.swift +++ b/src/ui/generic-components/text/TextField.swift @@ -4,7 +4,17 @@ class TextField: NSTextField { let insets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) convenience init(_ attributedString: NSAttributedString) { - self.init(labelWithAttributedString: attributedString) + self.init(labelWithAttributedString: TextField.forceLeftToRight(attributedString)) + } + + // we know the content to display should be left-to-right, so we force it to avoid displayed it right-to-left + static func forceLeftToRight(_ attributedString: NSAttributedString) -> NSMutableAttributedString { + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.alignment = .left + paragraphStyle.baseWritingDirection = .leftToRight + let forced = NSMutableAttributedString(attributedString: attributedString) + forced.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: forced.length)) + return forced } // NSTextField has 2px insets left and right by default; we remove those