| 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 NSString* EscapeStringForLocalizableStrings(NSString* string) { | 91 // Generates a NSDictionary mapping string IDs to localized strings. The |
| 92 NSString* slashEscapedString = | 92 // dictionary can be written as a Property List (only contains types that |
| 93 [string stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; | 93 // are valid in Propery Lists). |
| 94 return [slashEscapedString stringByReplacingOccurrencesOfString:@"\"" | 94 NSDictionary* GenerateLocalizableStringsDictionary( |
| 95 withString:@"\\\""]; | 95 const ui::DataPack& data_pack, |
| 96 } | 96 const char* locale, |
| 97 | 97 NSArray* resources, |
| 98 // Generate the content of the Localizable.string file for |locale| from the | 98 NSDictionary* resources_ids) { |
| 99 // resource data pack |data_pack|. The content should have the format of: | 99 NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; |
| 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]; | |
| 107 for (id resource : resources) { | 100 for (id resource : resources) { |
| 108 NSString* resource_name = nil; | 101 NSString* resource_name = nil; |
| 109 NSString* resource_output_name = nil; | 102 NSString* resource_output_name = nil; |
| 110 if ([resource isKindOfClass:[NSString class]]) { | 103 if ([resource isKindOfClass:[NSString class]]) { |
| 111 resource_name = resource; | 104 resource_name = resource; |
| 112 resource_output_name = resource; | 105 resource_output_name = resource; |
| 113 } else if ([resource isKindOfClass:[NSDictionary class]]) { | 106 } else if ([resource isKindOfClass:[NSDictionary class]]) { |
| 114 resource_name = [resource objectForKey:@"input"]; | 107 resource_name = [resource objectForKey:@"input"]; |
| 115 resource_output_name = [resource objectForKey:@"output"]; | 108 resource_output_name = [resource objectForKey:@"output"]; |
| 116 if (!resource_name || !resource_output_name) { | 109 if (!resource_name || !resource_output_name) { |
| 117 fprintf( | 110 fprintf( |
| 118 stderr, | 111 stderr, |
| 119 "ERROR: resources must be given in <string> or <dict> format.\n"); | 112 "ERROR: resources must be given in <string> or <dict> format.\n"); |
| 120 return nil; | 113 return nil; |
| 121 } | 114 } |
| 122 } else { | 115 } else { |
| 123 fprintf(stderr, | 116 fprintf(stderr, |
| 124 "ERROR: resources must be given in <string> or <dict> format.\n"); | 117 "ERROR: resources must be given in <string> or <dict> format.\n"); |
| 125 return nil; | 118 return nil; |
| 126 } | 119 } |
| 127 NSInteger resource_id = | 120 NSInteger resource_id = |
| 128 [[resources_ids objectForKey:resource_name] integerValue]; | 121 [[resources_ids objectForKey:resource_name] integerValue]; |
| 129 NSString* string = GetStringFromDataPack(data_pack, resource_id); | 122 NSString* string = GetStringFromDataPack(data_pack, resource_id); |
| 130 if (string) { | 123 if (string) { |
| 131 const char* output_string_name = [resource_output_name UTF8String]; | 124 [dictionary setObject:string forKey:resource_output_name]; |
| 132 [localizable_strings | |
| 133 appendFormat:@" \"%s\" = \"%@\";\n", output_string_name, | |
| 134 EscapeStringForLocalizableStrings(string)]; | |
| 135 } else { | 125 } else { |
| 136 fprintf(stderr, "ERROR: fail to load string '%s' for locale '%s'\n", | 126 fprintf(stderr, "ERROR: fail to load string '%s' for locale '%s'\n", |
| 137 [resource_name UTF8String], locale); | 127 [resource_name UTF8String], locale); |
| 138 return nil; | 128 return nil; |
| 139 } | 129 } |
| 140 } | 130 } |
| 141 | 131 |
| 142 return localizable_strings; | 132 return dictionary; |
| 143 } | 133 } |
| 144 | 134 |
| 145 NSDictionary* LoadResourcesListFromHeaders(NSArray* header_list, | 135 NSDictionary* LoadResourcesListFromHeaders(NSArray* header_list, |
| 146 NSString* root_header_dir) { | 136 NSString* root_header_dir) { |
| 147 if (![header_list count]) { | 137 if (![header_list count]) { |
| 148 fprintf(stderr, "ERROR: No header file in the config.\n"); | 138 fprintf(stderr, "ERROR: No header file in the config.\n"); |
| 149 return nil; | 139 return nil; |
| 150 } | 140 } |
| 151 NSMutableDictionary* resources_ids = | 141 NSMutableDictionary* resources_ids = |
| 152 [[[NSMutableDictionary alloc] init] autorelease]; | 142 [[[NSMutableDictionary alloc] init] autorelease]; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 [string_name UTF8String]); | 182 [string_name UTF8String]); |
| 193 return nil; | 183 return nil; |
| 194 } | 184 } |
| 195 [resources_ids setValue:[NSNumber numberWithInteger:string_id] | 185 [resources_ids setValue:[NSNumber numberWithInteger:string_id] |
| 196 forKey:string_name]; | 186 forKey:string_name]; |
| 197 } | 187 } |
| 198 } | 188 } |
| 199 return resources_ids; | 189 return resources_ids; |
| 200 } | 190 } |
| 201 | 191 |
| 202 // Save |localizable_strings| with |locale| to | 192 // Save |dictionary| as a Property List file (in binary1 encoding) |
| 203 // |output_dir|/|locale|.lproj/|output_filename|. | 193 // with |locale| to |output_dir|/|locale|.lproj/|output_filename|. |
| 204 bool SaveLocalizableFile(NSString* localizable_strings, | 194 bool SavePropertyList(NSDictionary* dictionary, |
| 205 NSString* locale, | 195 NSString* locale, |
| 206 NSString* output_dir, | 196 NSString* output_dir, |
| 207 NSString* output_filename) { | 197 NSString* output_filename) { |
| 208 // Compute the path to the output directory with locale. | 198 // Compute the path to the output directory with locale. |
| 209 NSString* output_path = [output_dir | 199 NSString* output_path = [output_dir |
| 210 stringByAppendingPathComponent:[NSString | 200 stringByAppendingPathComponent:[NSString |
| 211 stringWithFormat:@"%@.lproj", locale]]; | 201 stringWithFormat:@"%@.lproj", locale]]; |
| 212 | 202 |
| 213 // Prepare the directory. | 203 // Prepare the directory. |
| 214 NSFileManager* file_manager = [NSFileManager defaultManager]; | 204 NSFileManager* file_manager = [NSFileManager defaultManager]; |
| 215 if (![file_manager fileExistsAtPath:output_path] && | 205 if (![file_manager fileExistsAtPath:output_path] && |
| 216 ![file_manager createDirectoryAtPath:output_path | 206 ![file_manager createDirectoryAtPath:output_path |
| 217 withIntermediateDirectories:YES | 207 withIntermediateDirectories:YES |
| 218 attributes:nil | 208 attributes:nil |
| 219 error:nil]) { | 209 error:nil]) { |
| 220 fprintf(stderr, "ERROR: '%s' didn't exist or failed to create it\n", | 210 fprintf(stderr, "ERROR: '%s' didn't exist or failed to create it\n", |
| 221 [output_path UTF8String]); | 211 [output_path UTF8String]); |
| 222 return false; | 212 return false; |
| 223 } | 213 } |
| 224 | 214 |
| 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 |
| 225 // Save the strings to the disk. | 228 // Save the strings to the disk. |
| 226 output_path = [output_path stringByAppendingPathComponent:output_filename]; | 229 output_path = [output_path stringByAppendingPathComponent:output_filename]; |
| 227 if (![localizable_strings writeToFile:output_path | 230 if (![data writeToFile:output_path atomically:YES]) { |
| 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 NSString* localizable_strings = GenerateLocalizableStringsFileContent( | 361 NSDictionary* dictionary = GenerateLocalizableStringsDictionary( |
| 362 *data_pack, [locale UTF8String], output_strings, resources_ids); | 362 *data_pack, [locale UTF8String], output_strings, resources_ids); |
| 363 if (localizable_strings) { | 363 if (dictionary) { |
| 364 SaveLocalizableFile(localizable_strings, locale, output_dir, | 364 SavePropertyList(dictionary, locale, output_dir, output_name); |
| 365 output_name); | |
| 366 } else { | 365 } else { |
| 367 fprintf(stderr, "ERROR: Unable to create %s.\n", | 366 fprintf(stderr, "ERROR: Unable to create %s.\n", |
| 368 [output_name UTF8String]); | 367 [output_name UTF8String]); |
| 369 exit(1); | 368 exit(1); |
| 370 } | 369 } |
| 371 } | 370 } |
| 372 } | 371 } |
| 373 return 0; | 372 return 0; |
| 374 } | 373 } |
| OLD | NEW |