[objective-c] NSLocalizedString을 사용하는 모범 사례

(다른 모든 사람들과 마찬가지로) NSLocalizedString내 앱을 현지화 하는 데 사용 하고 있습니다.

불행히도 다음을 포함하여 몇 가지 “결점”이 있습니다 (NSLocalizedString 자체의 결함 일 필요는 없음).

  • Xcode에서 문자열에 대한 자동 완성이 없습니다. 이로 인해 오류가 발생하기 쉬울뿐만 아니라 번거 롭습니다.
  • 이미 존재하는 동등한 문자열을 알지 못했기 때문에 단순히 문자열을 다시 정의하게 될 수 있습니다 (예 : “비밀번호를 입력하십시오”대 “비밀번호를 먼저 입력하십시오”)
  • 자동 완성 문제와 마찬가지로 주석 문자열을 “기억”/ 복사해야합니다. 그렇지 않으면 genstring한 문자열에 대해 여러 주석이 생깁니다.
  • genstring이미 일부 문자열을 현지화 한 후 사용하려면 이전 현지화를 잃지 않도록주의해야합니다.
  • 전체 프로젝트에 동일한 문자열이 흩어져 있습니다. 예를 들어 NSLocalizedString(@"Abort", @"Cancel action")어디에서나 사용한 다음 코드 검토 NSLocalizedString(@"Cancel", @"Cancel action")에서 코드의 일관성을 높이기 위해 문자열의 이름을 바꾸도록 요청합니다 .

내가하는 일은 (그리고 많은 사람들이 이것을 찾은 후에 많은 사람들이 이것을하는 것으로 생각했습니다) 모든 현지화 코드 가있는 별도의 strings.h파일 을 갖는 것 #define입니다. 예를 들어

// In strings.h
#define NSLS_COMMON_CANCEL NSLocalizedString(@"Cancel", nil)
// Somewhere else
NSLog(@"%@", NSLS_COMMON_CANCEL);

이것은 본질적으로 코드 완성, 변수 이름을 변경하기위한 단일 위치 (더 이상 genstring 필요 없음) 및 자동 리팩터링을위한 고유 키워드를 제공합니다. 그러나 이것은 #define본질적으로 구조화되지 않은 (예를 들어 LocString.Common.Cancel 또는 이와 유사한) 명령문 으로 끝납니다 .

그래서, 이것은 다소 효과가 있지만 프로젝트에서 어떻게하는지 궁금합니다. NSLocalizedString의 사용을 단순화하는 다른 접근 방법이 있습니까? 캡슐화하는 프레임 워크가 있을까요?



답변

NSLocalizedString몇 가지 제한 사항이 있지만 Cocoa의 중심이기 때문에 현지화를 처리하기 위해 사용자 지정 코드를 작성하는 것은 부당합니다. 즉,이를 사용해야합니다. 약간의 툴링이 도움이 될 수 있습니다.

문자열 파일 업데이트

genstrings문자열 파일을 덮어 쓰고 이전의 모든 번역을 버립니다. 내가 쓴 update_strings.py를 이전 문자열 파일, 실행 구문 분석 할 수 genstrings있도록 수동으로 기존 번역을 복원 할 필요가 없다는 공백 및 채우기. 스크립트는 업데이트 할 때 너무 큰 차이를 피하기 위해 기존 문자열 파일을 가능한 한 가깝게 일치시킵니다.

문자열 이름 지정

NSLocalizedString광고 한대로 사용 하는 경우 :

NSLocalizedString(@"Cancel or continue?", @"Cancel notice message when a download takes too long to proceed");

서로 다른 상황에서 다른 의미를 가질 수 같은 영어 용어로 충돌 할 수있는 코드의 다른 부분에서 같은 문자열을 정의 결국 (수 OKCancel마음에 와서). 그렇기 때문에 항상 모듈 별 접두사와 매우 정확한 설명이있는 의미없는 올캡 문자열을 사용합니다.

NSLocalizedString(@"DOWNLOAD_CANCEL_OR_CONTINUE", @"Cancel notice window title when a download takes too long to proceed");

다른 장소에서 동일한 문자열 사용

동일한 문자열을 여러 번 사용하는 경우처럼 매크로를 사용하거나 View Controller 또는 데이터 소스에서 인스턴스 변수로 캐시 할 수 있습니다. 이 방법을 사용하면 설명이 반복되어 동일한 지역화 인스턴스 사이에서 오래되고 일관성이 없어 질 수 있습니다. 항상 혼란 스럽습니다. 인스턴스 변수는 기호이므로 가장 일반적인 번역에서 자동 완성 기능을 사용하고 특정 변수에 대해서는 “수동”문자열을 사용할 수 있습니다.이 문자열은 어쨌든 한 번만 발생합니다.

이 팁으로 Cocoa 현지화를 통해 생산성을 높이기를 바랍니다.


답변

Xcode에서 문자열의 자동 완성과 관련하여 https://github.com/questbeat/Lin을 시도 할 수 있습니다 .


답변

ndfred와 동의하지만 다음을 추가하고 싶습니다.

두 번째 파라미터는 … 기본값으로 사용할 수 있습니다 !!

(NSLocalizedStringWithDefaultValue는 genstring에서 제대로 작동하지 않으므로이 솔루션을 제안했습니다)

주석을 기본값으로 사용하는 NSLocalizedString을 사용하는 사용자 정의 구현은 다음과 같습니다.

1 . 사전 컴파일 된 헤더 (.pch 파일)에서 ‘NSLocalizedString’매크로를 재정의하십시오.

// cutom NSLocalizedString that use macro comment as default value
#import "LocalizationHandlerUtil.h"

#undef NSLocalizedString
#define NSLocalizedString(key,_comment) [[LocalizationHandlerUtil singleton] localizedString:key  comment:_comment]

2. 지역화 처리기를 구현할 클래스를 만듭니다.

#import "LocalizationHandlerUtil.h"

@implementation LocalizationHandlerUtil

static LocalizationHandlerUtil * singleton = nil;

+ (LocalizationHandlerUtil *)singleton
{
    return singleton;
}

__attribute__((constructor))
static void staticInit_singleton()
{
    singleton = [[LocalizationHandlerUtil alloc] init];
}

- (NSString *)localizedString:(NSString *)key comment:(NSString *)comment
{
    // default localized string loading
    NSString * localizedString = [[NSBundle mainBundle] localizedStringForKey:key value:key table:nil];

    // if (value == key) and comment is not nil -> returns comment
    if([localizedString isEqualToString:key] && comment !=nil)
        return comment;

    return localizedString;
}

@end

3. 그것을 사용하십시오!

앱 빌드 단계에서 실행 스크립트를 추가해야 각 빌드마다 Localizable.strings 파일이 업데이트됩니다. 즉, 현지화 된 새 문자열이 Localized.strings 파일에 추가됩니다.

내 빌드 단계 스크립트는 쉘 스크립트입니다.

Shell: /bin/sh
Shell script content: find . -name \*.m | xargs genstrings -o MyClassesFolder

따라서 코드에 다음 줄을 추가하면

self.title = NSLocalizedString(@"view_settings_title", @"Settings");

그런 다음 빌드를 수행하면 ./Localizable.scripts 파일에 다음 줄이 포함됩니다.

/* Settings */
"view_settings_title" = "view_settings_title";

그리고 ‘view_settings_title’의 키 == 값이므로 사용자 정의 LocalizedStringHandler는 주석, 즉 ‘Settings’를 반환합니다.

Voilà 🙂


답변

스위프트에서는 다음과 같은 것을 사용하고 있습니다.

NSLocalizedString("btn_yes", value: "Yes", comment: "Yes button")

value:기본 텍스트 값의 사용법에 유의하십시오 . 첫 번째 매개 변수는 번역 ID 역할을합니다. 이 value:매개 변수 를 사용하면 나중에 기본 텍스트를 변경할 수 있지만 번역 ID는 동일하게 유지됩니다. Localizable.strings 파일에는"btn_yes" = "Yes";

경우 value:매개 변수가 다음 사용되지 않은 첫 번째 매개 변수는 모두를 위해 사용되는 : 번역 ID과도 기본 텍스트 값. Localizable.strings 파일에는가 포함 "Yes" = "Yes";됩니다. 이런 종류의 지역화 파일 관리는 이상하게 보입니다. 특히 번역 된 텍스트가 길면 ID도 길다. 기본 텍스트 값의 문자가 변경 될 때마다 번역 ID도 변경됩니다. 외부 번역 시스템을 사용할 때 문제가 발생합니다. 번역 ID를 변경하는 것은 항상 원치 않을 수있는 새로운 번역 텍스트를 추가하는 것으로 이해됩니다.


답변

Localizable.strings를 여러 언어로 유지 관리하는 데 도움이되는 스크립트를 작성했습니다. 자동 완성에는 도움이되지 않지만 다음 명령을 사용하여 .strings 파일을 병합하는 데 도움이됩니다.

merge_strings.rb ja.lproj/Localizable.strings en.lproj/Localizable.strings

자세한 내용은 https://github.com/hiroshi/merge_strings를 참조하십시오.

당신 중 일부는 내가 희망하는 것이 유용하다고 생각합니다.


답변

누군가 스위프트 솔루션을 찾고 있다면. 여기에 정리 한 솔루션을 확인하고 싶을 수도 있습니다. SwiftyLocalization

몇 단계 만 설정하면 Google 스프레드 시트에서 매우 유연한 현지화 (설명, 사용자 정의 색상, 강조 표시, 글꼴, 여러 시트 등)가 가능합니다.

간단히 말해 단계는 다음과 같습니다. Google 스프레드 시트-> CSV 파일-> Localizable.strings

또한 키 검색 및 디코딩에 대한 인터페이스처럼 작동하는 구조체 인 Localizables.swift도 생성합니다 (키에서 문자열을 디코딩하는 방법을 수동으로 지정해야 함).

왜 이것이 좋습니까?

  1. 더 이상 모든 장소에서 일반 문자열로 키를 가질 필요가 없습니다.
  2. 컴파일시 잘못된 키가 감지되었습니다.
  3. Xcode는 자동 완성을 수행 할 수 있습니다.

지역화 가능한 키를 자동 완성 할 수있는 도구가 있습니다. 실제 변수에 대한 참조는 항상 유효한 키인지 확인하고 그렇지 않으면 컴파일되지 않습니다.

// It's defined as computed static var, so it's up-to-date every time you call. 
// You can also have your custom retrieval method there.

button.setTitle(Localizables.login.button_title_login, forState: .Normal)

이 프로젝트는 Google 앱 스크립트를 사용하여 시트-> CSV를 변환하고 Python 스크립트는 CSV 파일을 변환합니다-> Localizable.strings이 예제 시트를 빠르게 살펴보고 가능한 것을 알 수 있습니다.


답변

iOS 7 및 Xcode 5에서는 ‘Localization.strings’메소드를 사용하지 말고 새로운 ‘기본 현지화’메소드를 사용해야합니다. ‘기본 지역화’를 위해 Google을 사용하는 경우 몇 가지 자습서가 있습니다.

Apple Doc : 기본 현지화