Overview
Comment: | Implement support for localized strings |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
e731dc4c7597387cd8ec8211dc8730b7 |
User & Date: | js on 2017-01-10 19:39:13 |
Other Links: | manifest | tags |
Context
2017-01-10
| ||
19:51 | Do not use DATADIR as a define check-in: e3e38ed68d user: js tags: trunk | |
19:39 | Implement support for localized strings check-in: e731dc4c75 user: js tags: trunk | |
00:46 | Add files that I forgot to add check-in: 967b411ee5 user: js tags: trunk | |
Changes
Modified src/OFLocalization.h from [93e52fa91a] to [e9be33b3dd].
︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | /*! @file */ #define OF_LOCALIZED(ID, ...) \ [[OFLocalization sharedLocalization] \ localizedStringForID: ID \ fallback: __VA_ARGS__, nil] /*! * @class OFLocalization OFLocalization.h ObjFW/OFLocalization.h * * @brief A class for querying the locale and retrieving localized strings. */ @interface OFLocalization: OFObject { OFString *_language; OFString *_territory; of_string_encoding_t _encoding; OFString *_decimalPoint; } /** * The language of the locale. * * If the language is unknown, it is `nil`. */ | > > > > > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | /*! @file */ #define OF_LOCALIZED(ID, ...) \ [[OFLocalization sharedLocalization] \ localizedStringForID: ID \ fallback: __VA_ARGS__, nil] @class OFMutableArray OF_GENERIC(ObjectType); @class OFDictionary OF_GENERIC(KeyType, ObjectType); /*! * @class OFLocalization OFLocalization.h ObjFW/OFLocalization.h * * @brief A class for querying the locale and retrieving localized strings. */ @interface OFLocalization: OFObject { OFString *_language; OFString *_territory; of_string_encoding_t _encoding; OFString *_decimalPoint; OFMutableArray OF_GENERIC(OFDictionary OF_GENERIC(OFString*, id)*) *_localizedStrings; } /** * The language of the locale. * * If the language is unknown, it is `nil`. */ |
︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | /*! * @brief Returns the decimal point of the system's locale. * * @return The decimal point of the system's locale */ + (OFString*)decimalPoint; /*! * @brief Initializes the OFLocalization singleton with the specified locale. * * @warning You should never call this yourself, except if you do not use * @ref OFApplication. In this case, you need to allocate exactly one * instance of OFLocalization, which will be come the singleton, and * call this method. * * @param locale The locale used, as returned from `setlocale()` */ - initWithLocale: (char*)locale; /*! * @brief Returns the localized string for the specified ID, using the fallback * string if it cannot be looked up or is missing. * * @note This takes a variadic argument, terminated by `nil`, that consists of * pairs of variable names and variable values, which will be replaced * inside the localized string. For example, you can pass * `@"name", @"foo", nil`, causing `%[name]` to be replaced with `foo` in * the localized string. * * @note Generally, you want to use @ref OF_LOCALIZED instead, which also takes * care of the `nil` sentinel automatically. * * @param ID The ID for the localized string * @param fallback The fallback to use in case the localized string cannot be * looked up or is missing * @return The localized string */ - (OFString*)localizedStringForID: (OFConstantString*)ID fallback: (OFConstantString*)fallback, ... OF_SENTINEL; /** * @brief Returns the localized string for the specified ID, using the fallback * string if it cannot be looked up or is missing. * * @note This takes a variadic argument, terminated by `nil` and passed as * va_list, that consists of pairs of variable names and variable values, * which will be replaced inside the localized string. For example, you | > > > > > > > > > > > > > > > | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | /*! * @brief Returns the decimal point of the system's locale. * * @return The decimal point of the system's locale */ + (OFString*)decimalPoint; /*! * @brief Adds a directory to scan for language files. * * @param path The path to the directory to scan for language files */ + (void)addLanguageDirectory: (OFString*)path; /*! * @brief Initializes the OFLocalization singleton with the specified locale. * * @warning You should never call this yourself, except if you do not use * @ref OFApplication. In this case, you need to allocate exactly one * instance of OFLocalization, which will be come the singleton, and * call this method. * * @param locale The locale used, as returned from `setlocale()` */ - initWithLocale: (char*)locale; /*! * @brief Adds a directory to scan for language files. * * @param path The path to the directory to scan for language files */ - (void)addLanguageDirectory: (OFString*)path; /*! * @brief Returns the localized string for the specified ID, using the fallback * string if it cannot be looked up or is missing. * * @note This takes a variadic argument, terminated by `nil`, that consists of * pairs of variable names and variable values, which will be replaced * inside the localized string. For example, you can pass * `@"name", @"foo", nil`, causing `%[name]` to be replaced with `foo` in * the localized string. * * @note Generally, you want to use @ref OF_LOCALIZED instead, which also takes * care of the `nil` sentinel automatically. * * @param ID The ID for the localized string * @param fallback The fallback to use in case the localized string cannot be * looked up or is missing * @return The localized string */ - (OFString*)localizedStringForID: (OFConstantString*)ID fallback: (OFConstantString*)fallback, ... OF_SENTINEL; /** * @brief Returns the localized string for the specified ID, using the fallback * string if it cannot be looked up or is missing. * * @note This takes a variadic argument, terminated by `nil` and passed as * va_list, that consists of pairs of variable names and variable values, * which will be replaced inside the localized string. For example, you |
︙ | ︙ |
Modified src/OFLocalization.m from [ea48dae0ba] to [d001be40f2].
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include "config.h" #include <locale.h> #import "OFLocalization.h" #import "OFString.h" #import "OFInvalidArgumentException.h" static OFLocalization *sharedLocalization = nil; @implementation OFLocalization @synthesize language = _language, territory = _territory, encoding = _encoding; | > > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include "config.h" #include <locale.h> #import "OFLocalization.h" #import "OFString.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFInvalidArgumentException.h" static OFLocalization *sharedLocalization = nil; @implementation OFLocalization @synthesize language = _language, territory = _territory, encoding = _encoding; |
︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | return [sharedLocalization encoding]; } + (OFString*)decimalPoint { return [sharedLocalization decimalPoint]; } - initWithLocale: (char*)locale { self = [super init]; if (locale == NULL) { _encoding = OF_STRING_ENCODING_UTF_8; _decimalPoint = @"."; return self; } locale = of_strdup(locale); @try { char *tmp; /* We don't care for extras behind the @ */ if ((tmp = strrchr(locale, '@')) != NULL) *tmp = '\0'; /* Encoding */ if ((tmp = strrchr(locale, '.')) != NULL) { | > > > > > > > > > > > > > < < | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | return [sharedLocalization encoding]; } + (OFString*)decimalPoint { return [sharedLocalization decimalPoint]; } + (void)addLanguageDirectory: (OFString*)path { [sharedLocalization addLanguageDirectory: path]; } - initWithLocale: (char*)locale { self = [super init]; @try { _localizedStrings = [[OFMutableArray alloc] init]; } @catch (id e) { [self release]; @throw e; } if (locale == NULL) { _encoding = OF_STRING_ENCODING_UTF_8; _decimalPoint = @"."; return self; } locale = of_strdup(locale); @try { char *tmp; size_t tmpLen; /* We don't care for extras behind the @ */ if ((tmp = strrchr(locale, '@')) != NULL) *tmp = '\0'; /* Encoding */ if ((tmp = strrchr(locale, '.')) != NULL) { *tmp++ = '\0'; tmpLen = strlen(tmp); for (size_t i = 0; i < tmpLen; i++) tmp[i] = of_ascii_tolower(tmp[i]); if (strcmp(tmp, "utf8") == 0 || |
︙ | ︙ | |||
99 100 101 102 103 104 105 106 107 | else if (strcmp(tmp, "1252") == 0) _encoding = OF_STRING_ENCODING_WINDOWS_1252; } /* Territory */ if ((tmp = strrchr(locale, '_')) != NULL) { *tmp++ = '\0'; _territory = [[OFString alloc] initWithCString: tmp | > > > > > | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | else if (strcmp(tmp, "1252") == 0) _encoding = OF_STRING_ENCODING_WINDOWS_1252; } /* Territory */ if ((tmp = strrchr(locale, '_')) != NULL) { *tmp++ = '\0'; tmpLen = strlen(tmp); for (size_t i = 0; i < tmpLen; i++) tmp[i] = of_ascii_tolower(tmp[i]); _territory = [[OFString alloc] initWithCString: tmp encoding: OF_STRING_ENCODING_ASCII length: tmpLen]; } tmpLen = strlen(tmp); for (size_t i = 0; i < tmpLen; i++) tmp[i] = of_ascii_tolower(tmp[i]); _language = [[OFString alloc] initWithCString: locale encoding: OF_STRING_ENCODING_ASCII length: tmpLen]; _decimalPoint = [[OFString alloc] initWithCString: localeconv()->decimal_point encoding: _encoding]; } @catch (id e) { [self release]; @throw e; } @finally { free(locale); } sharedLocalization = self; return self; } - (void)dealloc { [_language release]; [_territory release]; [_decimalPoint release]; [_localizedStrings release]; [super dealloc]; } - (void)addLanguageDirectory: (OFString*)path { void *pool = objc_autoreleasePoolPush(); OFString *mapPath = [path stringByAppendingPathComponent: @"languages.json"]; OFDictionary *map = [[OFString stringWithContentsOfFile: mapPath] JSONValue]; OFString *languageFile; languageFile = [[map objectForKey: _language] objectForKey: _territory]; if (languageFile == nil) languageFile = [[map objectForKey: _language] objectForKey: @""]; if (languageFile == nil) { objc_autoreleasePoolPop(pool); return; } languageFile = [path stringByAppendingPathComponent: [languageFile stringByAppendingString: @".json"]]; [_localizedStrings addObject: [[OFString stringWithContentsOfFile: languageFile] JSONValue]]; objc_autoreleasePoolPop(pool); } - (OFString*)localizedStringForID: (OFConstantString*)ID fallback: (OFConstantString*)fallback, ... { OFString *ret; va_list args; |
︙ | ︙ | |||
144 145 146 147 148 149 150 | - (OFString*)localizedStringForID: (OFConstantString*)ID fallback: (OFConstantString*)fallback arguments: (va_list)arguments { OFMutableString *ret = [OFMutableString string]; void *pool = objc_autoreleasePoolPush(); | | < | > > > > > > > > > > > > > > > > > > > > > | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 | - (OFString*)localizedStringForID: (OFConstantString*)ID fallback: (OFConstantString*)fallback arguments: (va_list)arguments { OFMutableString *ret = [OFMutableString string]; void *pool = objc_autoreleasePoolPush(); const char *UTF8String = NULL; size_t last, UTF8StringLength; int state = 0; for (OFDictionary *strings in _localizedStrings) { id string = [strings objectForKey: ID]; if (string == nil) continue; if ([string isKindOfClass: [OFArray class]]) string = [string componentsJoinedByString: @""]; UTF8String = [string UTF8String]; UTF8StringLength = [string UTF8StringLength]; break; } if (UTF8String == NULL) { UTF8String = [fallback UTF8String]; UTF8StringLength = [fallback UTF8StringLength]; } state = 0; last = 0; for (size_t i = 0; i < UTF8StringLength; i++) { switch (state) { case 0: if (UTF8String[i] == '%') { [ret appendUTF8String: UTF8String + last length: i - last]; |
︙ | ︙ |
Modified utils/ofhttp/Makefile from [dda167b0c2] to [f803e607df].
︙ | ︙ | |||
8 9 10 11 12 13 14 | include ../../buildsys.mk PACKAGE_NAME = ofhttp ${PROG}: ${LIBOBJFW_DEP_LVL2} | | > > > > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | include ../../buildsys.mk PACKAGE_NAME = ofhttp ${PROG}: ${LIBOBJFW_DEP_LVL2} CPPFLAGS += -I../../src \ -I../../src/runtime \ -I../../src/exceptions \ -I../.. \ -DDATADIR=\"${datadir}\" LIBS := -L../../src -lobjfw ${LIBS} LD = ${OBJC} LDFLAGS += ${LDFLAGS_RPATH} |
Modified utils/ofhttp/OFHTTP.m from [2334e6806d] to [9a10462bff].
︙ | ︙ | |||
243 244 245 246 247 248 249 250 251 252 253 254 255 256 | { 'v', @"verbose", 0, &_verbose, NULL }, { '\0', nil, 0, NULL, NULL } }; OFOptionsParser *optionsParser = [OFOptionsParser parserWithOptions: options]; of_unichar_t option; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { case 'b': [self setBody: [optionsParser argument]]; break; case 'h': help(of_stdout, true, 0); | > > > | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | { 'v', @"verbose", 0, &_verbose, NULL }, { '\0', nil, 0, NULL, NULL } }; OFOptionsParser *optionsParser = [OFOptionsParser parserWithOptions: options]; of_unichar_t option; [OFLocalization addLanguageDirectory: [OFString pathWithComponents: [OFArray arrayWithObjects: @DATADIR, @"ofhttp", @"lang", nil]]]; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { case 'b': [self setBody: [optionsParser argument]]; break; case 'h': help(of_stdout, true, 0); |
︙ | ︙ |
Modified utils/ofhttp/lang/de.json from [28e8f2837c] to [0371c6a7bd].
1 2 3 4 5 | { "usage": "Benutzung: %[prog] -[cehHmoOPqv] url1 [url2 ...]\n", "full_usage": [ "\n", "Optionen:\n", | | | > | | | | | | < | | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { "usage": "Benutzung: %[prog] -[cehHmoOPqv] url1 [url2 ...]\n", "full_usage": [ "\n", "Optionen:\n", " -b --body Angegebene Datei als Body übergeben\n", " -c --continue Download von existierender Datei ", "fortsetzen\n", " -f --force Existierende Datei überschreiben\n", " -h --help Diese Hilfe anzeigen\n", " -H --header Einen Header (z.B. X-Foo:Bar) hinzufügen\n", " -m --method HTTP Request-Methode setzen\n", " -o --output Ausgabe-Dateiname angeben\n", " -O --detect-filename Dateiname mittels HEAD-Request ermitteln\n", " -P --proxy SOCKS5-Proxy angeben\n", " -q --quiet Ruhiger Modus (keine Ausgabe außer Fehler)", "\n", " -v --verbose Geschwätziger Modus (gibt Header aus)\n" ], "invalid_input_header": [ "%[prog]: Header müssen im Format Name:Wert sein!\n" ], "invalid_input_method": "%[prog]: Ungültige Request-Methode %[method]!\n", "invalid_input_proxy": "%[prog]: Proxy muss im Format Host:Port sein!\n", "long_argument_missing": "%[prog]: Argument für Option --%[opt] fehlt\n", |
︙ | ︙ |
Modified utils/ofhttp/lang/languages.json from [68d643bb62] to [59396279d5].
1 2 | { "de": { | | | | 1 2 3 4 5 6 7 8 | { "de": { "": "de" }, "german": { "": "de" } } |