summaryrefslogtreecommitdiffstats
path: root/chrome/common/extensions/extension_message_bundle.h
blob: 8f3078e830f53727dccaab0a6f57471a1d211a2d (plain)
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
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
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
100
101
102
103
104
105
106
107
108
109
110
111
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
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_MESSAGE_BUNDLE_H_
#define CHROME_COMMON_EXTENSIONS_EXTENSION_MESSAGE_BUNDLE_H_
#pragma once

#include <map>
#include <string>
#include <vector>

#include "base/memory/linked_ptr.h"

class DictionaryValue;

// Contains localized extension messages for one locale. Any messages that the
// locale does not provide are pulled from the default locale.
class ExtensionMessageBundle {
 public:
  typedef std::map<std::string, std::string> SubstitutionMap;
  typedef std::vector<linked_ptr<DictionaryValue> > CatalogVector;

  // JSON keys of interest for messages file.
  static const char* kContentKey;
  static const char* kMessageKey;
  static const char* kPlaceholdersKey;

  // Begin/end markers for placeholders and messages
  static const char* kPlaceholderBegin;
  static const char* kPlaceholderEnd;
  static const char* kMessageBegin;
  static const char* kMessageEnd;

  // Reserved message names in the dictionary.
  // Update i18n documentation when adding new reserved value.
  static const char* kUILocaleKey;
  // See http://code.google.com/apis/gadgets/docs/i18n.html#BIDI for
  // description.
  // TODO(cira): point to chrome docs once they are out.
  static const char* kBidiDirectionKey;
  static const char* kBidiReversedDirectionKey;
  static const char* kBidiStartEdgeKey;
  static const char* kBidiEndEdgeKey;
  // Extension id gets added in the
  // browser/renderer_host/resource_message_filter.cc to enable message
  // replacement for non-localized extensions.
  static const char* kExtensionIdKey;

  // Values for some of the reserved messages.
  static const char* kBidiLeftEdgeValue;
  static const char* kBidiRightEdgeValue;

  // Creates ExtensionMessageBundle or returns NULL if there was an error.
  // Expects locale_catalogs to be sorted from more specific to less specific,
  // with default catalog at the end.
  static ExtensionMessageBundle* Create(const CatalogVector& locale_catalogs,
                                        std::string* error);

  // Get message from the catalog with given key.
  // Returned message has all of the internal placeholders resolved to their
  // value (content).
  // Returns empty string if it can't find a message.
  // We don't use simple GetMessage name, since there is a global
  // #define GetMessage GetMessageW override in Chrome code.
  std::string GetL10nMessage(const std::string& name) const;

  // Get message from the given catalog with given key.
  static std::string GetL10nMessage(const std::string& name,
                                    const SubstitutionMap& dictionary);

  // Number of messages in the catalog.
  // Used for unittesting only.
  size_t size() const { return dictionary_.size(); }

  // Replaces all __MSG_message__ with values from the catalog.
  // Returns false if there is a message in text that's not defined in the
  // dictionary.
  bool ReplaceMessages(std::string* text, std::string* error) const;
  // Static version that accepts dictionary.
  static bool ReplaceMessagesWithExternalDictionary(
      const SubstitutionMap& dictionary, std::string* text, std::string* error);

  // Replaces each occurance of variable placeholder with its value.
  // I.e. replaces __MSG_name__ with value from the catalog with the key "name".
  // Returns false if for a valid message/placeholder name there is no matching
  // replacement.
  // Public for easier unittesting.
  static bool ReplaceVariables(const SubstitutionMap& variables,
                               const std::string& var_begin,
                               const std::string& var_end,
                               std::string* message,
                               std::string* error);

  // Allow only ascii 0-9, a-z, A-Z, and _ in the variable name.
  // Returns false if the input is empty or if it has illegal characters.
  static bool IsValidName(const std::string& name);

  // Getter for dictionary_.
  const SubstitutionMap* dictionary() const { return &dictionary_; }

  ~ExtensionMessageBundle();

 private:
  // Testing friend.
  friend class ExtensionMessageBundleTest;

  // Use Create to create ExtensionMessageBundle instance.
  ExtensionMessageBundle();

  // Initializes the instance from the contents of vector of catalogs.
  // If the key is not present in more specific catalog we fall back to next one
  // (less specific).
  // Returns false on error.
  bool Init(const CatalogVector& locale_catalogs, std::string* error);

  // Appends locale specific reserved messages to the dictionary.
  // Returns false if there was a conflict with user defined messages.
  bool AppendReservedMessagesForLocale(const std::string& application_locale,
                                       std::string* error);

  // Helper methods that navigate JSON tree and return simplified message.
  // They replace all $PLACEHOLDERS$ with their value, and return just key/value
  // of the message.
  bool GetMessageValue(const std::string& key,
                       const DictionaryValue& catalog,
                       std::string* value,
                       std::string* error) const;

  // Get all placeholders for a given message from JSON subtree.
  bool GetPlaceholders(const DictionaryValue& name_tree,
                       const std::string& name_key,
                       SubstitutionMap* placeholders,
                       std::string* error) const;

  // For a given message, replaces all placeholders with their actual value.
  // Returns false if replacement failed (see ReplaceVariables).
  bool ReplacePlaceholders(const SubstitutionMap& placeholders,
                           std::string* message,
                           std::string* error) const;

  // Holds all messages for application locale.
  SubstitutionMap dictionary_;
};

///////////////////////////////////////////////////////////////////////////////
//
// Renderer helper typedefs and functions.
//
///////////////////////////////////////////////////////////////////////////////

// A map of message name to message.
typedef std::map<std::string, std::string> L10nMessagesMap;

// A map of extension ID to l10n message map.
typedef std::map<std::string, L10nMessagesMap > ExtensionToL10nMessagesMap;

// Returns the extension_id to messages map.
ExtensionToL10nMessagesMap* GetExtensionToL10nMessagesMap();

// Returns message map that matches given extension_id, or NULL.
L10nMessagesMap* GetL10nMessagesMap(const std::string& extension_id);

#endif  // CHROME_COMMON_EXTENSIONS_EXTENSION_MESSAGE_BUNDLE_H_