| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Helper tool that is built and run during a build to pull strings from the | 5 // Helper tool that is built and run during a build to pull strings from the |
| 6 // GRD files and generate a localized string files needed for iOS app bundles. | 6 // GRD files and generate a localized string files needed for iOS app bundles. |
| 7 // Arguments: | 7 // Arguments: |
| 8 // -p dir_to_data_pak | 8 // -p dir_to_data_pak |
| 9 // -o output_dir | 9 // -o output_dir |
| 10 // -c config_file | 10 // -c config_file |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 encoding:NSUTF8StringEncoding] autorelease]; | 81 encoding:NSUTF8StringEncoding] autorelease]; |
| 82 } else if (data_pack.GetTextEncodingType() == ui::DataPack::UTF16) { | 82 } else if (data_pack.GetTextEncodingType() == ui::DataPack::UTF16) { |
| 83 return [[[NSString alloc] initWithBytes:data.data() | 83 return [[[NSString alloc] initWithBytes:data.data() |
| 84 length:data.length() | 84 length:data.length() |
| 85 encoding:NSUTF16LittleEndianStringEncoding] | 85 encoding:NSUTF16LittleEndianStringEncoding] |
| 86 autorelease]; | 86 autorelease]; |
| 87 } | 87 } |
| 88 return nil; | 88 return nil; |
| 89 } | 89 } |
| 90 | 90 |
| 91 // Generates a NSDictionary mapping string IDs to localized strings. The | 91 NSString* EscapeStringForLocalizableStrings(NSString* string) { |
| 92 // dictionary can be written as a Property List (only contains types that | 92 NSString* slashEscapedString = |
| 93 // are valid in Propery Lists). | 93 [string stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; |
| 94 NSDictionary* GenerateLocalizableStringsDictionary( | 94 return [slashEscapedString stringByReplacingOccurrencesOfString:@"\"" |
| 95 const ui::DataPack& data_pack, | 95 withString:@"\\\""]; |
| 96 const char* locale, | 96 } |
| 97 NSArray* resources, | 97 |
| 98 NSDictionary* resources_ids) { | 98 // Generate the content of the Localizable.string file for |locale| from the |
| 99 NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; | 99 // resource data pack |data_pack|. The content should have the format of: |
| 100 // "IDS_PRINT_TO_PHONE" = "Print to phone jobs are available."; |
| 101 // "IDS_SNAPSHOTS" = "Snapshots are available."; |
| 102 NSString* GenerateLocalizableStringsFileContent(const ui::DataPack& data_pack, |
| 103 const char* locale, |
| 104 NSArray* resources, |
| 105 NSDictionary* resources_ids) { |
| 106 NSMutableString* localizable_strings = [NSMutableString string]; |
| 100 for (id resource : resources) { | 107 for (id resource : resources) { |
| 101 NSString* resource_name = nil; | 108 NSString* resource_name = nil; |
| 102 NSString* resource_output_name = nil; | 109 NSString* resource_output_name = nil; |
| 103 if ([resource isKindOfClass:[NSString class]]) { | 110 if ([resource isKindOfClass:[NSString class]]) { |
| 104 resource_name = resource; | 111 resource_name = resource; |
| 105 resource_output_name = resource; | 112 resource_output_name = resource; |
| 106 } else if ([resource isKindOfClass:[NSDictionary class]]) { | 113 } else if ([resource isKindOfClass:[NSDictionary class]]) { |
| 107 resource_name = [resource objectForKey:@"input"]; | 114 resource_name = [resource objectForKey:@"input"]; |
| 108 resource_output_name = [resource objectForKey:@"output"]; | 115 resource_output_name = [resource objectForKey:@"output"]; |
| 109 if (!resource_name || !resource_output_name) { | 116 if (!resource_name || !resource_output_name) { |
| 110 fprintf( | 117 fprintf( |
| 111 stderr, | 118 stderr, |
| 112 "ERROR: resources must be given in <string> or <dict> format.\n"); | 119 "ERROR: resources must be given in <string> or <dict> format.\n"); |
| 113 return nil; | 120 return nil; |
| 114 } | 121 } |
| 115 } else { | 122 } else { |
| 116 fprintf(stderr, | 123 fprintf(stderr, |
| 117 "ERROR: resources must be given in <string> or <dict> format.\n"); | 124 "ERROR: resources must be given in <string> or <dict> format.\n"); |
| 118 return nil; | 125 return nil; |
| 119 } | 126 } |
| 120 NSInteger resource_id = | 127 NSInteger resource_id = |
| 121 [[resources_ids objectForKey:resource_name] integerValue]; | 128 [[resources_ids objectForKey:resource_name] integerValue]; |
| 122 NSString* string = GetStringFromDataPack(data_pack, resource_id); | 129 NSString* string = GetStringFromDataPack(data_pack, resource_id); |
| 123 if (string) { | 130 if (string) { |
| 124 [dictionary setObject:string forKey:resource_output_name]; | 131 const char* output_string_name = [resource_output_name UTF8String]; |
| 132 [localizable_strings |
| 133 appendFormat:@" \"%s\" = \"%@\";\n", output_string_name, |
| 134 EscapeStringForLocalizableStrings(string)]; |
| 125 } else { | 135 } else { |
| 126 fprintf(stderr, "ERROR: fail to load string '%s' for locale '%s'\n", | 136 fprintf(stderr, "ERROR: fail to load string '%s' for locale '%s'\n", |
| 127 [resource_name UTF8String], locale); | 137 [resource_name UTF8String], locale); |
| 128 return nil; | 138 return nil; |
| 129 } | 139 } |
| 130 } | 140 } |
| 131 | 141 |
| 132 return dictionary; | 142 return localizable_strings; |
| 133 } | 143 } |
| 134 | 144 |
| 135 NSDictionary* LoadResourcesListFromHeaders(NSArray* header_list, | 145 NSDictionary* LoadResourcesListFromHeaders(NSArray* header_list, |
| 136 NSString* root_header_dir) { | 146 NSString* root_header_dir) { |
| 137 if (![header_list count]) { | 147 if (![header_list count]) { |
| 138 fprintf(stderr, "ERROR: No header file in the config.\n"); | 148 fprintf(stderr, "ERROR: No header file in the config.\n"); |
| 139 return nil; | 149 return nil; |
| 140 } | 150 } |
| 141 NSMutableDictionary* resources_ids = | 151 NSMutableDictionary* resources_ids = |
| 142 [[[NSMutableDictionary alloc] init] autorelease]; | 152 [[[NSMutableDictionary alloc] init] autorelease]; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 [string_name UTF8String]); | 192 [string_name UTF8String]); |
| 183 return nil; | 193 return nil; |
| 184 } | 194 } |
| 185 [resources_ids setValue:[NSNumber numberWithInteger:string_id] | 195 [resources_ids setValue:[NSNumber numberWithInteger:string_id] |
| 186 forKey:string_name]; | 196 forKey:string_name]; |
| 187 } | 197 } |
| 188 } | 198 } |
| 189 return resources_ids; | 199 return resources_ids; |
| 190 } | 200 } |
| 191 | 201 |
| 192 // Save |dictionary| as a Property List file (in binary1 encoding) | 202 // Save |localizable_strings| with |locale| to |
| 193 // with |locale| to |output_dir|/|locale|.lproj/|output_filename|. | 203 // |output_dir|/|locale|.lproj/|output_filename|. |
| 194 bool SavePropertyList(NSDictionary* dictionary, | 204 bool SaveLocalizableFile(NSString* localizable_strings, |
| 195 NSString* locale, | 205 NSString* locale, |
| 196 NSString* output_dir, | 206 NSString* output_dir, |
| 197 NSString* output_filename) { | 207 NSString* output_filename) { |
| 198 // Compute the path to the output directory with locale. | 208 // Compute the path to the output directory with locale. |
| 199 NSString* output_path = [output_dir | 209 NSString* output_path = [output_dir |
| 200 stringByAppendingPathComponent:[NSString | 210 stringByAppendingPathComponent:[NSString |
| 201 stringWithFormat:@"%@.lproj", locale]]; | 211 stringWithFormat:@"%@.lproj", locale]]; |
| 202 | 212 |
| 203 // Prepare the directory. | 213 // Prepare the directory. |
| 204 NSFileManager* file_manager = [NSFileManager defaultManager]; | 214 NSFileManager* file_manager = [NSFileManager defaultManager]; |
| 205 if (![file_manager fileExistsAtPath:output_path] && | 215 if (![file_manager fileExistsAtPath:output_path] && |
| 206 ![file_manager createDirectoryAtPath:output_path | 216 ![file_manager createDirectoryAtPath:output_path |
| 207 withIntermediateDirectories:YES | 217 withIntermediateDirectories:YES |
| 208 attributes:nil | 218 attributes:nil |
| 209 error:nil]) { | 219 error:nil]) { |
| 210 fprintf(stderr, "ERROR: '%s' didn't exist or failed to create it\n", | 220 fprintf(stderr, "ERROR: '%s' didn't exist or failed to create it\n", |
| 211 [output_path UTF8String]); | 221 [output_path UTF8String]); |
| 212 return false; | 222 return false; |
| 213 } | 223 } |
| 214 | 224 |
| 215 // Convert to property list in binary format. | |
| 216 NSError* error = nil; | |
| 217 NSData* data = [NSPropertyListSerialization | |
| 218 dataWithPropertyList:dictionary | |
| 219 format:NSPropertyListBinaryFormat_v1_0 | |
| 220 options:0 | |
| 221 error:&error]; | |
| 222 if (!data) { | |
| 223 fprintf(stderr, "ERROR: conversion to property list failed: %s\n", | |
| 224 [[error localizedDescription] UTF8String]); | |
| 225 return false; | |
| 226 } | |
| 227 | |
| 228 // Save the strings to the disk. | 225 // Save the strings to the disk. |
| 229 output_path = [output_path stringByAppendingPathComponent:output_filename]; | 226 output_path = [output_path stringByAppendingPathComponent:output_filename]; |
| 230 if (![data writeToFile:output_path atomically:YES]) { | 227 if (![localizable_strings writeToFile:output_path |
| 228 atomically:YES |
| 229 encoding:NSUTF16StringEncoding |
| 230 error:nil]) { |
| 231 fprintf(stderr, "ERROR: Failed to write out '%s'\n", | 231 fprintf(stderr, "ERROR: Failed to write out '%s'\n", |
| 232 [output_filename UTF8String]); | 232 [output_filename UTF8String]); |
| 233 return false; | 233 return false; |
| 234 } | 234 } |
| 235 | 235 |
| 236 return true; | 236 return true; |
| 237 } | 237 } |
| 238 | 238 |
| 239 } // namespace | 239 } // namespace |
| 240 | 240 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 fprintf(stderr, "ERROR: Output without name.\n"); | 351 fprintf(stderr, "ERROR: Output without name.\n"); |
| 352 exit(1); | 352 exit(1); |
| 353 } | 353 } |
| 354 NSArray* output_strings = [output objectForKey:@"strings"]; | 354 NSArray* output_strings = [output objectForKey:@"strings"]; |
| 355 if (![output_strings count]) { | 355 if (![output_strings count]) { |
| 356 fprintf(stderr, "ERROR: Output without strings: %s.\n", | 356 fprintf(stderr, "ERROR: Output without strings: %s.\n", |
| 357 [output_name UTF8String]); | 357 [output_name UTF8String]); |
| 358 exit(1); | 358 exit(1); |
| 359 } | 359 } |
| 360 | 360 |
| 361 NSDictionary* dictionary = GenerateLocalizableStringsDictionary( | 361 NSString* localizable_strings = GenerateLocalizableStringsFileContent( |
| 362 *data_pack, [locale UTF8String], output_strings, resources_ids); | 362 *data_pack, [locale UTF8String], output_strings, resources_ids); |
| 363 if (dictionary) { | 363 if (localizable_strings) { |
| 364 SavePropertyList(dictionary, locale, output_dir, output_name); | 364 SaveLocalizableFile(localizable_strings, locale, output_dir, |
| 365 output_name); |
| 365 } else { | 366 } else { |
| 366 fprintf(stderr, "ERROR: Unable to create %s.\n", | 367 fprintf(stderr, "ERROR: Unable to create %s.\n", |
| 367 [output_name UTF8String]); | 368 [output_name UTF8String]); |
| 368 exit(1); | 369 exit(1); |
| 369 } | 370 } |
| 370 } | 371 } |
| 371 } | 372 } |
| 372 return 0; | 373 return 0; |
| 373 } | 374 } |
| OLD | NEW |