From effc52561fdcdf37151cb6ac2715696009914abb Mon Sep 17 00:00:00 2001 From: Noah Nuebling Date: Wed, 28 Feb 2024 17:27:18 +0100 Subject: [PATCH] Moved Localization/Code stuff over to setting the value of untranslated keys to the key iself instead of leaving the value empty. This should make it clearer to the user that these are missing translations instead of just having no text at all which can look broken. --- App/SupportFiles/Info.plist | 2 +- Helper/SupportFiles/Info.plist | 2 +- Localization/Code/Localization Readme.md | 49 +++++++++++++++++++ Localization/Code/Shared/shared.py | 2 +- .../Code/StateOfLocalization/script.py | 39 ++++++++++++--- Localization/Code/UpdateStrings/script.py | 38 +++++++++++--- Localization/ko.lproj/Localizable.strings | 12 ++--- Localization/vi.lproj/Localizable.strings | 2 +- Localization/zh-HK.lproj/Localizable.strings | 12 ++--- .../zh-Hans.lproj/Localizable.strings | 12 ++--- .../zh-Hant.lproj/Localizable.strings | 12 ++--- Mouse Fix.xcodeproj/project.pbxproj | 4 +- .../xcshareddata/xcschemes/App.xcscheme | 1 - 13 files changed, 142 insertions(+), 45 deletions(-) create mode 100644 Localization/Code/Localization Readme.md diff --git a/App/SupportFiles/Info.plist b/App/SupportFiles/Info.plist index 041de4c26..54bf1ed46 100644 --- a/App/SupportFiles/Info.plist +++ b/App/SupportFiles/Info.plist @@ -34,7 +34,7 @@ CFBundleVersion - 22350 + 22356 LSApplicationCategoryType public.app-category.utilities NSHumanReadableCopyright diff --git a/Helper/SupportFiles/Info.plist b/Helper/SupportFiles/Info.plist index 371bfcc52..4ecb56011 100644 --- a/Helper/SupportFiles/Info.plist +++ b/Helper/SupportFiles/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 22350 + 22356 LSApplicationCategoryType public.app-category.utilities LSBackgroundOnly diff --git a/Localization/Code/Localization Readme.md b/Localization/Code/Localization Readme.md new file mode 100644 index 000000000..3419ec522 --- /dev/null +++ b/Localization/Code/Localization Readme.md @@ -0,0 +1,49 @@ +# Localization > Code + +## StateOfLocalization + +(All of these commands are for the fish shell) + +**Install dependencies** + +``` +python3 -m venv env;\ +source env/bin/activate.fish;\ +python3 -m pip install -r Localization/Code/StateOfLocalization/requirements.txt; +``` + +**Run the script** + +``` +python3 Localization/Code/StateOfLocalization/script.py --api_key <...> +``` +(Use --help for an explanation of the args) + +**Deactivate the venv** + +``` +deactivate +``` + +## UpdateStrings + +(All of these commands are for the fish shell) + +**Install dependencies** + +``` +python3 -m venv env;\ +source env/bin/activate.fish;\ +python3 -m pip install -r Localization/Code/UpdateStrings/requirements.txt; +``` + +**Run the script** + +``` +python3 Localization/Code/UpdateStrings/script.py +``` +(Use --help for an explanation of the args) + +``` +deactivate +``` diff --git a/Localization/Code/Shared/shared.py b/Localization/Code/Shared/shared.py index 3bde6cc2f..3f402f54f 100644 --- a/Localization/Code/Shared/shared.py +++ b/Localization/Code/Shared/shared.py @@ -401,7 +401,7 @@ def find_localization_files(repo_root, website_root=None, basetypes=['IB', 'stri for b in files_absolute: # Validate _, extension = os.path.splitext(b) - assert extension == '.md', f'Folder at {b}, contained file with extension {extension}' + assert extension == '.md', f'Folder at {b} contained file with extension {extension}' # Append markdown file result.append({ 'base': b, 'repo': mmf_repo, 'basetype': 'gh-markdown' }) diff --git a/Localization/Code/StateOfLocalization/script.py b/Localization/Code/StateOfLocalization/script.py index 3d0da4bb1..7351574d8 100644 --- a/Localization/Code/StateOfLocalization/script.py +++ b/Localization/Code/StateOfLocalization/script.py @@ -64,7 +64,7 @@ def main(): parser = argparse.ArgumentParser() - parser.add_argument('--api_key', required=True, help="See Apple Note 'MMF Localization Script Access Token'") + parser.add_argument('--api_key', required=False, help="If no API key is supplied, the result will be printed to the console instead of uploaded to GitHub || To find the API key, see Apple Note 'MMF Localization Script Access Token'") parser.add_argument('--print_latest_for', required=False, help="Debugging tool. Print the latest changes for each key for each translation file whose path contains this value.") args = parser.parse_args() @@ -78,7 +78,12 @@ def main(): missing_analysis = analyze_missing_localization_files(files) analysis = analyze_localization_files(files, args.print_latest_for) markdown = markdown_from_analysis(analysis, missing_analysis) - upload_markdown(args.api_key, markdown) + + if args.api_key: + upload_markdown(args.api_key, markdown) + else: + print("No API key was supplied. Printing the result to the console instead of uploading to GitHub:\n\n") + print(markdown) # # Debug @@ -348,6 +353,10 @@ def markdown_from_analysis(files, missing_files): empty_str = '\n- '.join(map(lambda x: f"Base file: {translation_to_markdown(x['key'], x['base_value'], file_type)}\n Translation: {translation_to_markdown(x['key'], x['value'], file_type)}", sorted(translation_dict['empty_translations'], key=lambda x: x['key']))) if len(empty_str) > 0: content_str += f"\n\n**Empty translations**\n\nThe following key-value-pairs are empty in the translation but not empty in the base file. It looks like they have not yet been translated:\n\n- {empty_str}" + + equal_to_key_str = '\n- '.join(map(lambda x: f"Base file: {translation_to_markdown(x['key'], x['base_value'], file_type)}\n Translation: {translation_to_markdown(x['key'], x['value'], file_type)}", sorted(translation_dict['equal_to_key_translations'], key=lambda x: x['key']))) + if len(equal_to_key_str) > 0: + content_str += f"\n\n**Equal-to-key translations**\n\nThe following key-value-pairs are have a value that is equal to the key. It looks like they have not yet been translated:\n\n- {equal_to_key_str}" # Build strings for outdated translations @@ -693,8 +702,8 @@ def analyze_localization_files(files, print_latest_for): At time of writing, is_ok_count is used for 2 things in the code: 1. When the is_ok_count increases for a kv-pair in a commit, that's treated as a `change` to the kv-pair in `get_latest_change_for_translation_keys()`. This should behave well in all scenarios. E.g. when is_ok_count increases the kv-pair will not be considered outdated. But when the base value changes afterwards, the translation will be considered outdated again. - 2. When the is_ok_count for a kv-pair is greater 0, then we filter that kv-pair from the 'unchanged_translations' and the 'empty_translations'. - Important consideration why this makes sense: + 2. When the is_ok_count for a kv-pair is greater 0, then we filter that kv-pair from the 'unchanged_translations', the 'empty_translations' and the 'equal_to_key_translations'. + Important consideration why this makes sense: The only time a translation would 'accidentally' be exactly the same as the base (unchanged) is if the translation has been generated by Xcode and never been touched by a human. I'm not totally sure if this behaviour also makes sense for 'empty_translations'. @@ -709,6 +718,7 @@ def analyze_localization_files(files, print_latest_for): 'superfluous_translations': [{ 'key': , 'value': }, ...], 'unchanged_translations': [{ 'key': , 'value': }, ...], 'empty_translations': [{ 'key': , 'value': , 'base_value': }, ...], + 'equal_to_key_translations': [{ 'key': , 'value': , 'base_value': }, ...], 'outdated_translations': { '': { 'latest_base_change': { @@ -879,24 +889,39 @@ def analyze_localization_files(files, print_latest_for): unchanged_translations = [] empty_translations = [] + equal_to_key_translations = [] + for k in common_keys: b = base_keys_and_values[k]['value'] t = translation_keys_and_values[k]['value'] + # Check conditions: + # Context: + # - is_ok: !IS_OK flag is set. This is explained elsewhere in this file. + # - is_equal: Not sure atm when this happens + # - is_key: Apples `extractLocStrings` tool sets the value of the kv-pairs equal to the key when it generates a .strings file based on source code. + # - b_is_empty and t_is_empty: + # - We leave some values in .strings files intentionally empty because they are defined elsewhere. In those cases the base value will be empty, and the translation value being also empty shouldn't be reported as a translation issue. + # - If only the translation value is empty but not the base value that's a translation issue. Not sure atm when this happens. + is_ok = t['is_ok_count'] > 0 - is_equal = b['text'] == t['text'] + is_equal = t['text'] == b['text'] + is_key = t['text'] == k b_is_empty = len(b['text']) == 0 or b['text'] == '<>' t_is_empty = len(t['text']) == 0 or t['text'] == '<>' both_are_empty = b_is_empty and t_is_empty if is_equal and not both_are_empty and not is_ok: unchanged_translations.append({'key': k, 'value': t['text']}) - if not b_is_empty and t_is_empty and not is_ok: + elif not b_is_empty and t_is_empty and not is_ok: empty_translations.append({'key': k, 'value': t['text'], 'base_value': b['text']}) + elif is_key and not is_ok: + equal_to_key_translations.append({'key': k, 'value': t['text'], 'base_value': b['text']}) translation_dict['unchanged_translations'] = unchanged_translations translation_dict['empty_translations'] = empty_translations + translation_dict['equal_to_key_translations'] = equal_to_key_translations # Log print(f' Analyze when keys last changed...') @@ -1303,4 +1328,4 @@ def is_website_repo(git_repo): # Call main # if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/Localization/Code/UpdateStrings/script.py b/Localization/Code/UpdateStrings/script.py index 3b7d5eecf..4669805af 100644 --- a/Localization/Code/UpdateStrings/script.py +++ b/Localization/Code/UpdateStrings/script.py @@ -117,11 +117,19 @@ def update_strings_files(files, type, repo_root): (if type == 'sourcecode') Update .strings files to match source code files which they translate (if type == 'IB') Update .strings files to match .xib/.storyboard files which they translate - Discussion: - - In update_ib_comments we don't update development language files - because there are none, since development language strings are directly inside the ib files. - But in this function, we also update en.lproj/Localizable.strings. Maybe we should've specified development language values directly in the source code using `NSLocalizedStringWithDefaultValue` instead of inside en.lproj. That way we wouldn't need en.lproj at all. - Not sure anymore why we chose to do it with en.lproj instead of all source code for English. But either way, I don't think it's worth it to change now. - Note: + Discussion: + + - On location of English (development language) UI strings: + + Explanation: + - For IB, the English strings are directly in the source (IB) files + (This isn't the case for every Xcode project, but we chose do t the case for the MMF project.) + - On the other hand, for sourcecode, the English strings not directly in the source (sourcecode) files, instead they are inside en.lproj/Localizable.strings. + + Thoughts: + - In update_ib_comments we don't update English .strings files - because currently in MMF there are no English .strings files for IB files - that's because the IB files hold the English UI strings directly. + - Maybe we should've specified development language values directly in the source code using `NSLocalizedStringWithDefaultValue` instead of inside en.lproj. That way we wouldn't need en.lproj at all. + - Not sure anymore why we chose to do it with en.lproj instead of all source code for English. But either way, I don't think it's worth it to change now. """ print(f"\nUpdating strings files type {type}...") @@ -134,7 +142,13 @@ def update_strings_files(files, type, repo_root): for file_dict in files: + # Autogenerate fresh .strings file from the source files (IB/sourcecode) using Apples tools + # Notes: + # - The fresh strings file will have its comments and keys up-to-date with the source file + # - We store the content of these fresh strings files inside generated_content + generated_content = '' + if type == 'sourcecode': source_code_files = shared.find_files_with_extensions(['m','c','cp','mm','swift'], ['env/', 'venv/', 'iOS-Polynomial-Regression-master/', './Test/']) source_code_files_str = ' '.join(map(lambda p: p.replace(' ', r'\ '), source_code_files)) @@ -148,18 +162,23 @@ def update_strings_files(files, type, repo_root): else: assert False + # Find all the .strings files that translate the source files translation_file_paths = list(file_dict['translations'].keys()) if type == 'sourcecode': translation_file_paths.append(file_dict['base']) for path in translation_file_paths: - + + # Update the translation .strings file + # using the keys and comments of the generated .strings file content = shared.read_file(path, 'utf-8') new_content, mods, ordered_keys = updated_strings_file_content(content, generated_content, path, repo_root) + # Store updates if new_content != content: updated_files.append({"path": path, "new_content": new_content}) + # Debug modss.append({'path': path, 'mods': mods, 'ordered_keys': ordered_keys}) # Return @@ -237,15 +256,18 @@ def log_modifications(modss): def updated_strings_file_content(content, generated_content, file_path, repo_root): """ - At the time of writing: + What this does at time of writing: - Copy over all comments from `generated_content` to `content` - Insert kv-pair + comment from `generated_content` into `content` - if the kv-pair is not found in `content` - Reorder kv-pairs in `content` to match `generated_content` """ # Parse both contents + # Notes: + # - Apples `extractLocStrings` tool which generated the (generated_content) sets all values to the key. We can use remove_value=True, to remove these autogenerated values. + # - Update: I think it's better to keep the keys. Makes it more clear to users that 'this string is not translated' instead of having no text at all which looks broken. parse = parse_strings_file_content(content, file_path) - generated_parse = parse_strings_file_content(generated_content, file_path, remove_value=True) # `extractLocStrings` sets all values to the key for some reason, so we remove them. + generated_parse = parse_strings_file_content(generated_content, file_path, remove_value=False) # Record modifications for diagnositics mods = [] diff --git a/Localization/ko.lproj/Localizable.strings b/Localization/ko.lproj/Localizable.strings index 5cc05d4c5..9357647c0 100644 --- a/Localization/ko.lproj/Localizable.strings +++ b/Localization/ko.lproj/Localizable.strings @@ -15,7 +15,7 @@ "already-using-defaults-toast.5" = "이미 __5개 버튼__의 마우스에 해당하는 기본 설정을 사용 중입니다."; /* First draft: Version %@ || Note: %@ will be replaced by the app version, e.g. '3.0.0 (22027)' */ -"app-version" = ""; +"app-version" = "app-version"; /* First draft: */ "apple-key-fallback.backward" = "<되감기 키>"; @@ -213,10 +213,10 @@ "effect.mission-control.hint" = "Mission Control을 엽니다."; /* First draft: Primary Click */ -"effect.primary-click" = ""; +"effect.primary-click" = "effect.primary-click"; /* First draft: Works like clicking %@ on a standard mouse. */ -"effect.primary-click.hint" = ""; +"effect.primary-click.hint" = "effect.primary-click.hint"; /* First draft: Keyboard Shortcut... */ "effect.record-shortcut" = "키보드 단축키..."; @@ -231,10 +231,10 @@ "effect.right-space.hint" = "우측 Space로 이동합니다."; /* First draft: Secondary Click */ -"effect.secondary-click" = ""; +"effect.secondary-click" = "effect.secondary-click"; /* First draft: Works like clicking %@ on a standard mouse. */ -"effect.secondary-click.hint" = ""; +"effect.secondary-click.hint" = "effect.secondary-click.hint"; /* First draft: Works like pressing '%@' on your keyboard */ "effect.shortcut.hint" = "키보드 상의 '%@'를 누르는 것처럼 동작합니다."; @@ -246,7 +246,7 @@ "effect.smart-zoom.hint" = "Safari 등의 앱에서 콘텐츠를 확대하거나 축소합니다.\n \n이는 Apple 트랙패드에서 두 손가락으로 이중 탭하는 것과 같습니다."; /* First draft: If you have **problems enabling** the app, click [here](https://github.com/noah-nuebling/mac-mouse-fix/discussions/categories/guides). */ -"enable-timeout-toast" = ""; +"enable-timeout-toast" = "enable-timeout-toast"; /* First draft: **Primary Mouse Button** can't be used\nPlease try another button */ "forbidden-capture-toast.1" = "**마우스 주 버튼**은 사용할 수 없습니다.\n다른 버튼으로 다시 시도하십시오."; diff --git a/Localization/vi.lproj/Localizable.strings b/Localization/vi.lproj/Localizable.strings index 22e6e8c5b..4d9fbd199 100644 --- a/Localization/vi.lproj/Localizable.strings +++ b/Localization/vi.lproj/Localizable.strings @@ -246,7 +246,7 @@ "effect.smart-zoom.hint" = "Phóng to hoặc thu nhỏ trong Safari và các ứng dụng khác.\n \nHoạt động như nhấp bằng hai ngón tay trên Apple Trackpad."; /* First draft: If you have **problems enabling** the app, click [here](https://github.com/noah-nuebling/mac-mouse-fix/discussions/categories/guides). */ -"enable-timeout-toast" = ""; +"enable-timeout-toast" = "enable-timeout-toast"; /* First draft: **Primary Mouse Button** can't be used\nPlease try another button */ "forbidden-capture-toast.1" = "**Nút chính** không thể được áp dụng\nVui lòng chọn một nút khác"; diff --git a/Localization/zh-HK.lproj/Localizable.strings b/Localization/zh-HK.lproj/Localizable.strings index b877124ba..b7562972a 100644 --- a/Localization/zh-HK.lproj/Localizable.strings +++ b/Localization/zh-HK.lproj/Localizable.strings @@ -24,7 +24,7 @@ "already-using-defaults-toast.5" = "你**已經在使用**預設的**五鍵**滑鼠設定"; /* First draft: Version %@ || Note: %@ will be replaced by the app version, e.g. '3.0.0 (22027)' */ -"app-version" = ""; +"app-version" = "app-version"; /* First draft: */ "apple-key-fallback.backward" = "􀊉〔回帶鍵〕"; @@ -222,10 +222,10 @@ "effect.mission-control.hint" = "顯示「指揮中心」"; /* First draft: Primary Click */ -"effect.primary-click" = ""; +"effect.primary-click" = "effect.primary-click"; /* First draft: Works like clicking %@ on a standard mouse. */ -"effect.primary-click.hint" = ""; +"effect.primary-click.hint" = "effect.primary-click.hint"; /* First draft: Keyboard Shortcut... */ "effect.record-shortcut" = "鍵盤快捷鍵"; @@ -240,10 +240,10 @@ "effect.right-space.hint" = "向右移動一個空間"; /* First draft: Secondary Click */ -"effect.secondary-click" = ""; +"effect.secondary-click" = "effect.secondary-click"; /* First draft: Works like clicking %@ on a standard mouse. */ -"effect.secondary-click.hint" = ""; +"effect.secondary-click.hint" = "effect.secondary-click.hint"; /* First draft: Works like pressing '%@' on your keyboard */ "effect.shortcut.hint" = "作用相當於在你的鍵盤上按下「%@」"; @@ -255,7 +255,7 @@ "effect.smart-zoom.hint" = "在Safari和其他應用程式中放大或縮小。\n \n作用相當於在Apple觸控板上用兩指點兩下"; /* First draft: If you have **problems enabling** the app, click [here](https://github.com/noah-nuebling/mac-mouse-fix/discussions/categories/guides). */ -"enable-timeout-toast" = ""; +"enable-timeout-toast" = "enable-timeout-toast"; /* First draft: **Primary Mouse Button** can't be used\nPlease try another button */ "forbidden-capture-toast.1" = "不能使用**主要滑鼠按鈕**\n請換一個按鈕再試"; diff --git a/Localization/zh-Hans.lproj/Localizable.strings b/Localization/zh-Hans.lproj/Localizable.strings index dc07522a5..0979333f5 100644 --- a/Localization/zh-Hans.lproj/Localizable.strings +++ b/Localization/zh-Hans.lproj/Localizable.strings @@ -24,7 +24,7 @@ "already-using-defaults-toast.5" = "您**已经在使用**默认的**五鍵**鼠标设置"; /* First draft: Version %@ || Note: %@ will be replaced by the app version, e.g. '3.0.0 (22027)' */ -"app-version" = ""; +"app-version" = "app-version"; /* First draft: */ "apple-key-fallback.backward" = "􀊉〔倒回键〕"; @@ -222,10 +222,10 @@ "effect.mission-control.hint" = "显示“调度中心”"; /* First draft: Primary Click */ -"effect.primary-click" = ""; +"effect.primary-click" = "effect.primary-click"; /* First draft: Works like clicking %@ on a standard mouse. */ -"effect.primary-click.hint" = ""; +"effect.primary-click.hint" = "effect.primary-click.hint"; /* First draft: Keyboard Shortcut... */ "effect.record-shortcut" = "键盘快捷键"; @@ -240,10 +240,10 @@ "effect.right-space.hint" = "向右移动一个空间"; /* First draft: Secondary Click */ -"effect.secondary-click" = ""; +"effect.secondary-click" = "effect.secondary-click"; /* First draft: Works like clicking %@ on a standard mouse. */ -"effect.secondary-click.hint" = ""; +"effect.secondary-click.hint" = "effect.secondary-click.hint"; /* First draft: Works like pressing '%@' on your keyboard */ "effect.shortcut.hint" = "作用相当于在您的键盘上按下“%@”"; @@ -255,7 +255,7 @@ "effect.smart-zoom.hint" = "在Safari和其他应用程序中放大或缩小。\n \n作用相当于在Apple触控板上用双指轻点两下"; /* First draft: If you have **problems enabling** the app, click [here](https://github.com/noah-nuebling/mac-mouse-fix/discussions/categories/guides). */ -"enable-timeout-toast" = ""; +"enable-timeout-toast" = "enable-timeout-toast"; /* First draft: **Primary Mouse Button** can't be used\nPlease try another button */ "forbidden-capture-toast.1" = "不能使用**鼠标主键**\n请换一个按钮再试"; diff --git a/Localization/zh-Hant.lproj/Localizable.strings b/Localization/zh-Hant.lproj/Localizable.strings index f6a6e51e5..04380b1c0 100644 --- a/Localization/zh-Hant.lproj/Localizable.strings +++ b/Localization/zh-Hant.lproj/Localizable.strings @@ -24,7 +24,7 @@ "already-using-defaults-toast.5" = "您**已經在使用**預設的**五鍵**滑鼠設定"; /* First draft: Version %@ || Note: %@ will be replaced by the app version, e.g. '3.0.0 (22027)' */ -"app-version" = ""; +"app-version" = "app-version"; /* First draft: */ "apple-key-fallback.backward" = "􀊉〔倒轉鍵〕"; @@ -222,10 +222,10 @@ "effect.mission-control.hint" = "顯示「指揮中心」"; /* First draft: Primary Click */ -"effect.primary-click" = ""; +"effect.primary-click" = "effect.primary-click"; /* First draft: Works like clicking %@ on a standard mouse. */ -"effect.primary-click.hint" = ""; +"effect.primary-click.hint" = "effect.primary-click.hint"; /* First draft: Keyboard Shortcut... */ "effect.record-shortcut" = "鍵盤快速鍵"; @@ -240,10 +240,10 @@ "effect.right-space.hint" = "向右移動一個空間"; /* First draft: Secondary Click */ -"effect.secondary-click" = ""; +"effect.secondary-click" = "effect.secondary-click"; /* First draft: Works like clicking %@ on a standard mouse. */ -"effect.secondary-click.hint" = ""; +"effect.secondary-click.hint" = "effect.secondary-click.hint"; /* First draft: Works like pressing '%@' on your keyboard */ "effect.shortcut.hint" = "作用相當於在您的鍵盤上按下「%@」"; @@ -255,7 +255,7 @@ "effect.smart-zoom.hint" = "在Safari和其他應用程式中放大或縮小。\n \n作用相當於在Apple觸控式軌跡板上用兩指點兩下"; /* First draft: If you have **problems enabling** the app, click [here](https://github.com/noah-nuebling/mac-mouse-fix/discussions/categories/guides). */ -"enable-timeout-toast" = ""; +"enable-timeout-toast" = "enable-timeout-toast"; /* First draft: **Primary Mouse Button** can't be used\nPlease try another button */ "forbidden-capture-toast.1" = "不能使用**主要滑鼠按鈕**\n請換一個按鈕再試"; diff --git a/Mouse Fix.xcodeproj/project.pbxproj b/Mouse Fix.xcodeproj/project.pbxproj index 525e4d60a..c7dc8e04f 100644 --- a/Mouse Fix.xcodeproj/project.pbxproj +++ b/Mouse Fix.xcodeproj/project.pbxproj @@ -2358,6 +2358,7 @@ 4FF8C89D28955DC4007EC31F /* CoolTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoolTimer.swift; sourceTree = ""; }; 4FF8C8A028956DDD007EC31F /* ButtonModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModifiers.swift; sourceTree = ""; }; 4FF8C8A22895AACB007EC31F /* Buttons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Buttons.swift; sourceTree = ""; }; + 4FF8F3A92B8F8BD3005ACF3D /* Localization Readme.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "Localization Readme.md"; sourceTree = ""; }; 4FF93058288026FC0007CCA7 /* PolynomialCappedAccelerationCurve.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PolynomialCappedAccelerationCurve.swift; sourceTree = ""; }; 4FF9305D288060100007CCA7 /* PolyFit.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PolyFit.cpp; sourceTree = ""; }; 4FF9305E288060100007CCA7 /* PolyFit.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PolyFit.hpp; sourceTree = ""; }; @@ -6588,10 +6589,10 @@ 4F909D1528A0C3D2009349A2 /* Localization */ = { isa = PBXGroup; children = ( + 4F909D1928A0C3D2009349A2 /* Localization Readme.md */, 4FC7D5CB2B455A1C002AED77 /* Code */, 4F909D1728A0C3D2009349A2 /* Localizable.strings */, 4F6B02C228AD9E4400B5BA93 /* Localizable.stringsdict */, - 4F909D1928A0C3D2009349A2 /* Localization Readme.md */, 4F97DFFF298732E500012BAC /* LocalizationUtility.h */, 4F97E000298732E500012BAC /* LocalizationUtility.m */, ); @@ -6837,6 +6838,7 @@ 4FC7D5CB2B455A1C002AED77 /* Code */ = { isa = PBXGroup; children = ( + 4FF8F3A92B8F8BD3005ACF3D /* Localization Readme.md */, 4FC7D5CC2B455A1C002AED77 /* StateOfLocalization */, 4FC7D5CF2B455A1C002AED77 /* UpdateStrings */, 4FC7D5D22B455A1C002AED77 /* Shared */, diff --git a/Mouse Fix.xcodeproj/xcshareddata/xcschemes/App.xcscheme b/Mouse Fix.xcodeproj/xcshareddata/xcschemes/App.xcscheme index 76f53babc..285ae5f7a 100644 --- a/Mouse Fix.xcodeproj/xcshareddata/xcschemes/App.xcscheme +++ b/Mouse Fix.xcodeproj/xcshareddata/xcschemes/App.xcscheme @@ -54,7 +54,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "en" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO"