diff --git a/modules/angular2/src/facade/lang.dart b/modules/angular2/src/facade/lang.dart index bab4f285c1..41f7a8dd58 100644 --- a/modules/angular2/src/facade/lang.dart +++ b/modules/angular2/src/facade/lang.dart @@ -1,6 +1,6 @@ library angular.core.facade.lang; -export 'dart:core' show Type, RegExp, print, DateTime; +export 'dart:core' show Type, RegExp, print, DateTime, Uri; import 'dart:math' as math; import 'dart:convert' as convert; import 'dart:async' show Future, Zone; @@ -376,3 +376,7 @@ num bitWiseAnd(List values) { var val = values.reduce((num a, num b) => (a as int) & (b as int)); return val as num; } + +String escape(String s) { + return Uri.encodeComponent(s); +} \ No newline at end of file diff --git a/modules/angular2/src/facade/lang.ts b/modules/angular2/src/facade/lang.ts index bbe947ee18..27d90ffed0 100644 --- a/modules/angular2/src/facade/lang.ts +++ b/modules/angular2/src/facade/lang.ts @@ -18,6 +18,7 @@ export interface BrowserNodeGlobal { clearTimeout: Function; setInterval: Function; clearInterval: Function; + encodeURI: Function; } // TODO(jteplitz602): Load WorkerGlobalScope from lib.webworker.d.ts file #3492 @@ -473,3 +474,7 @@ export function bitWiseOr(values: number[]): number { export function bitWiseAnd(values: number[]): number { return values.reduce((a, b) => { return a & b; }); } + +export function escape(s: string): string { + return _global.encodeURI(s); +} \ No newline at end of file diff --git a/modules/angular2/src/i18n/message.ts b/modules/angular2/src/i18n/message.ts new file mode 100644 index 0000000000..2ad922d2ff --- /dev/null +++ b/modules/angular2/src/i18n/message.ts @@ -0,0 +1,21 @@ +import {isPresent, escape} from 'angular2/src/facade/lang'; + +/** + * A message extracted from a template. + * + * The identity of a message is comprised of `content` and `meaning`. + * + * `description` is additional information provided to the translator. + */ +export class Message { + constructor(public content: string, public meaning: string, public description: string) {} +} + +/** + * Computes the id of a message + */ +export function id(m: Message): string { + let meaning = isPresent(m.meaning) ? m.meaning : ""; + let content = isPresent(m.content) ? m.content : ""; + return escape(`$ng|${meaning}|${content}`); +} \ No newline at end of file diff --git a/modules/angular2/src/i18n/message_extractor.ts b/modules/angular2/src/i18n/message_extractor.ts index 9fdf0d2b7e..21fabe9592 100644 --- a/modules/angular2/src/i18n/message_extractor.ts +++ b/modules/angular2/src/i18n/message_extractor.ts @@ -13,21 +13,11 @@ import {isPresent, isBlank} from 'angular2/src/facade/lang'; import {StringMapWrapper} from 'angular2/src/facade/collection'; import {Parser} from 'angular2/src/core/change_detection/parser/parser'; import {Interpolation} from 'angular2/src/core/change_detection/parser/ast'; +import {Message, id} from './message'; const I18N_ATTR = "i18n"; const I18N_ATTR_PREFIX = "i18n-"; -/** - * A message extracted from a template. - * - * The identity of a message is comprised of `content` and `meaning`. - * - * `description` is additional information provided to the translator. - */ -export class Message { - constructor(public content: string, public meaning: string, public description: string) {} -} - /** * All messages extracted from a template. */ @@ -56,9 +46,8 @@ export class I18nExtractionError extends ParseError { export function removeDuplicates(messages: Message[]): Message[] { let uniq: {[key: string]: Message} = {}; messages.forEach(m => { - let key = `$ng__${m.meaning}__|${m.content}`; - if (!StringMapWrapper.contains(uniq, key)) { - uniq[key] = m; + if (!StringMapWrapper.contains(uniq, id(m))) { + uniq[id(m)] = m; } }); return StringMapWrapper.values(uniq); diff --git a/modules/angular2/test/i18n/message_extractor_spec.ts b/modules/angular2/test/i18n/message_extractor_spec.ts index ab15741ce0..7b1d1a8b3b 100644 --- a/modules/angular2/test/i18n/message_extractor_spec.ts +++ b/modules/angular2/test/i18n/message_extractor_spec.ts @@ -12,7 +12,8 @@ import { } from 'angular2/testing_internal'; import {HtmlParser} from 'angular2/src/compiler/html_parser'; -import {MessageExtractor, Message, removeDuplicates} from 'angular2/src/i18n/message_extractor'; +import {MessageExtractor, removeDuplicates} from 'angular2/src/i18n/message_extractor'; +import {Message} from 'angular2/src/i18n/message'; import {Parser} from 'angular2/src/core/change_detection/parser/parser'; import {Lexer} from 'angular2/src/core/change_detection/parser/lexer'; diff --git a/modules/angular2/test/i18n/message_spec.ts b/modules/angular2/test/i18n/message_spec.ts new file mode 100644 index 0000000000..50d9e56cc1 --- /dev/null +++ b/modules/angular2/test/i18n/message_spec.ts @@ -0,0 +1,27 @@ +import { + AsyncTestCompleter, + beforeEach, + ddescribe, + describe, + expect, + iit, + inject, + it, + xdescribe, + xit +} from 'angular2/testing_internal'; + +import {Message, id} from 'angular2/src/i18n/message'; + +export function main() { + ddescribe('Message', () => { + describe("id", () => { + it("should return a different id for messages with and without the meaning", () => { + let m1 = new Message("content", "meaning", null); + let m2 = new Message("content", null, null); + expect(id(m1)).toEqual(id(m1)); + expect(id(m1)).not.toEqual(id(m2)); + }); + }); + }); +}