Używam (jak wszyscy inni) NSLocalizedString
do lokalizowania mojej aplikacji.
Niestety, istnieje kilka „wad” (niekoniecznie wina samego NSLocalizedString), w tym
- Brak autouzupełniania dla ciągów w Xcode. To sprawia, że praca jest nie tylko podatna na błędy, ale także męcząca.
- Może się zdarzyć, że zmienisz definicję ciągu tylko dlatego, że nie wiedziałeś, że istnieje już równoważny ciąg (np. „Wprowadź hasło” zamiast „Najpierw wprowadź hasło”)
- Podobnie jak w przypadku problemu z autouzupełnianiem, musisz "zapamiętać" / skopiować ciągi komentarzy, w przeciwnym razie
genstring
skończy się wiele komentarzy dla jednego ciągu - Jeśli chcesz używać
genstring
po zlokalizowaniu niektórych ciągów, musisz uważać, aby nie stracić starych lokalizacji. - Te same struny są rozrzucone po całym projekcie. Na przykład był używany
NSLocalizedString(@"Abort", @"Cancel action")
wszędzie, a następnie Code Review prosi o zmianę nazwy ciąguNSLocalizedString(@"Cancel", @"Cancel action")
na, aby kod był bardziej spójny.
To, co robię (i po kilku poszukiwaniach na SO, doszedłem do wniosku, że wiele osób to robi), to posiadanie oddzielnego strings.h
pliku, w którym mam #define
cały kod lokalizacji. Na przykład
// In strings.h
#define NSLS_COMMON_CANCEL NSLocalizedString(@"Cancel", nil)
// Somewhere else
NSLog(@"%@", NSLS_COMMON_CANCEL);
Zasadniczo zapewnia to uzupełnianie kodu, pojedyncze miejsce do zmiany nazw zmiennych (więc nie ma już potrzeby tworzenia genstringów) oraz unikalne słowo kluczowe do automatycznej refaktoryzacji. Jednak odbywa się to kosztem zakończenia całej masy #define
instrukcji, które nie są z natury uporządkowane (np. Jak LocString.Common.Cancel lub coś w tym rodzaju).
Tak więc, chociaż działa to dość dobrze, zastanawiałem się, jak robicie to w swoich projektach. Czy istnieją inne metody upraszczania korzystania z NSLocalizedString? Czy może w ogóle istnieje struktura, która ją zawiera?
Odpowiedzi:
NSLocalizedString
ma kilka ograniczeń, ale jest tak centralny dla Cocoa, że pisanie własnego kodu do obsługi lokalizacji jest nierozsądne, co oznacza, że będziesz musiał go użyć. To powiedziawszy, trochę narzędzi może pomóc, oto jak postępuję:Aktualizacja pliku ciągów
genstrings
nadpisuje twoje pliki łańcuchowe, odrzucając wszystkie poprzednie tłumaczenia. Napisałem update_strings.py, aby przeanalizować stary plik ciągów, uruchomićgenstrings
i wypełnić puste miejsca, aby nie trzeba było ręcznie przywracać istniejących tłumaczeń. Skrypt próbuje jak najdokładniej dopasować istniejące pliki łańcuchowe, aby uniknąć zbyt dużego różnicowania podczas ich aktualizacji.Nazywanie twoich strun
Jeśli używasz
NSLocalizedString
zgodnie z reklamą:Może się zdarzyć, że zdefiniujesz ten sam ciąg w innej części kodu, co może być sprzeczne, ponieważ ten sam angielski termin może mieć różne znaczenie w różnych kontekstach (
OK
iCancel
przyjdzie Ci do głowy). Dlatego zawsze używam nic nie znaczącego, składającego się z wielkich liter z przedrostkiem specyficznym dla modułu i bardzo dokładnym opisem:Używanie tego samego ciągu w różnych miejscach
Jeśli używasz tego samego ciągu wiele razy, możesz użyć makra tak jak wcześniej lub buforować je jako zmienną wystąpienia w kontrolerze widoku lub źródle danych. W ten sposób nie będziesz musiał powtarzać opisu, który może stać się nieaktualny i niespójny między instancjami tej samej lokalizacji, co zawsze jest mylące. Ponieważ zmienne instancji są symbolami, będziesz mógł używać autouzupełniania w tych najpopularniejszych tłumaczeniach i używać ciągów "ręcznych" dla konkretnych, co i tak wystąpiłoby tylko raz.
Mam nadzieję, że dzięki tym wskazówkom będziesz bardziej produktywny z lokalizacją Cocoa!
źródło
genstrings
niegestring
.Jeśli chodzi o autouzupełnianie ciągów w Xcode, możesz spróbować https://github.com/questbeat/Lin .
źródło
Zgadzam się z ndfred, ale chciałbym to dodać:
Drugi parametr może być użyty jako ... wartość domyślna !!
(NSLocalizedStringWithDefaultValue nie działa poprawnie z genstringiem, dlatego zaproponowałem to rozwiązanie)
Oto moja implementacja niestandardowa, która używa NSLocalizedString, która używa komentarza jako wartości domyślnej:
1. We wstępnie skompilowanym nagłówku (pliku .pch) przedefiniuj makro „NSLocalizedString”:
2. utworzyć klasę do implementacji modułu obsługi lokalizacji
3. Użyj tego!
Upewnij się, że dodałeś skrypt uruchamiania w fazach tworzenia aplikacji, aby plik Localizable.strings był aktualizowany przy każdej kompilacji, tj. Nowy zlokalizowany ciąg zostanie dodany do pliku Localized.strings:
Mój skrypt fazy budowania to skrypt powłoki:
Więc kiedy dodasz ten nowy wiersz w swoim kodzie:
Następnie wykonaj kompilację, twój plik ./Localizable.scripts będzie zawierał tę nową linię:
A ponieważ klucz == wartość dla „view_settings_title”, niestandardowy LocalizedStringHandler zwróci komentarz, tj. „Ustawienia”
Voilà :-)
źródło
W Swift używam np. Przycisku „Tak” w tym przypadku:
Zwróć uwagę na użycie
value:
jako domyślnej wartości tekstowej. Pierwszy parametr służy jako identyfikator tłumaczenia. Zaletą używaniavalue:
parametru jest to, że domyślny tekst można zmienić później, ale identyfikator tłumaczenia pozostaje taki sam. Plik Localizable.strings będzie zawierał"btn_yes" = "Yes";
Jeśli
value:
parametr nie został użyty, to pierwszy parametr byłby używany zarówno dla identyfikatora tłumaczenia, jak i dla domyślnej wartości tekstowej. Plik Localizable.strings będzie zawierał"Yes" = "Yes";
. Ten sposób zarządzania plikami lokalizacyjnymi wydaje się dziwny. Zwłaszcza jeśli przetłumaczony tekst jest długi, identyfikator również jest długi. Za każdym razem, gdy zmienia się dowolny znak domyślnej wartości tekstowej, zmienia się również identyfikator tłumaczenia. Prowadzi to do problemów, gdy używane są zewnętrzne systemy tłumaczeniowe. Zmiana identyfikatora tłumaczenia jest rozumiana jako dodanie nowego tekstu tłumaczenia, co nie zawsze jest pożądane.źródło
Napisałem skrypt, aby pomóc w utrzymaniu Localizable.strings w wielu językach. Chociaż nie pomaga to w autouzupełnianiu, pomaga scalić pliki .strings za pomocą polecenia:
Aby uzyskać więcej informacji, zobacz: https://github.com/hiroshi/merge_strings
Mam nadzieję, że niektórzy z was uznają to za przydatne.
źródło
Jeśli ktoś szuka szybkiego rozwiązania. Możesz sprawdzić moje rozwiązanie, które stworzyłem tutaj: SwiftyLocalization
Dzięki kilku krokom konfiguracji uzyskasz bardzo elastyczną lokalizację w arkuszu kalkulacyjnym Google (komentarz, niestandardowy kolor, wyróżnienie, czcionka, wiele arkuszy i więcej).
Krótko mówiąc, kroki to: Arkusz kalkulacyjny Google -> Pliki CSV -> Localizable.strings
Co więcej, generuje również Localizables.swift, strukturę, która działa jak interfejsy do pobierania i dekodowania klucza (chociaż musisz ręcznie określić sposób dekodowania ciągu znaków z klucza).
Dlaczego to jest świetne?
Chociaż istnieją narzędzia, które mogą automatycznie uzupełniać lokalizowalny klucz. Odniesienie do rzeczywistej zmiennej zapewni, że jest to zawsze prawidłowy klucz, w przeciwnym razie nie będzie się kompilować.
Projekt wykorzystuje Google App Script do konwersji Arkuszy -> CSV i skryptu Python do konwersji plików CSV -> Localizable.strings. Możesz rzucić okiem na ten przykładowy arkusz, aby dowiedzieć się, co jest możliwe.
źródło
w iOS 7 i Xcode 5 należy unikać stosowania metody „Localization.strings” i używać nowej metody „podstawowej lokalizacji”. Istnieje kilka samouczków, jeśli wyszukujesz w Google `` lokalizację podstawową ''
Dokument Apple: lokalizacja podstawowa
źródło
źródło
Ja sam często daję się ponieść kodowaniu, zapominając o umieszczaniu wpisów w plikach .strings. W ten sposób mam skrypty pomocnicze, aby dowiedzieć się, co powinienem umieścić z powrotem w plikach .strings i przetłumaczyć.
Ponieważ używam własnego makra zamiast NSLocalizedString, proszę przejrzeć i zaktualizować skrypt przed użyciem, jak założyłem dla uproszczenia, że nil jest używany jako drugi parametr NSLocalizedString. Część, którą chciałbyś zmienić, to
Po prostu zastąp go czymś, co pasuje do makra i użycia NSLocalizedString.
Oto skrypt, naprawdę potrzebujesz tylko części 3. Reszta to łatwiejsze zobaczenie, skąd to wszystko się bierze:
Plik wyjściowy zawiera klucze znalezione w kodzie, ale nie w pliku Localizable.strings. Oto próbka:
Z pewnością można go bardziej polerować, ale pomyślałem, że podzielę się.
źródło