@@ -93,9 +93,24 @@ bool SerializedLocalizationWriter::emit(llvm::StringRef filePath) {
9393 return OS.has_error ();
9494}
9595
96+ void LocalizationProducer::initializeIfNeeded () {
97+ if (state != NotInitialized)
98+ return ;
99+
100+ if (initializeImpl ())
101+ state = Initialized;
102+ else
103+ state = FailedInitialization;
104+ }
105+
96106llvm::StringRef
97107LocalizationProducer::getMessageOr (swift::DiagID id,
98108 llvm::StringRef defaultMessage) {
109+ initializeIfNeeded ();
110+ if (getState () == FailedInitialization) {
111+ return defaultMessage;
112+ }
113+
99114 auto localizedMessage = getMessage (id);
100115 if (localizedMessage.empty ())
101116 return defaultMessage;
@@ -108,14 +123,22 @@ LocalizationProducer::getMessageOr(swift::DiagID id,
108123 return localizedMessage;
109124}
110125
126+ LocalizationProducerState LocalizationProducer::getState () const {
127+ return state;
128+ }
129+
111130SerializedLocalizationProducer::SerializedLocalizationProducer (
112131 std::unique_ptr<llvm::MemoryBuffer> buffer, bool printDiagnosticNames)
113132 : LocalizationProducer(printDiagnosticNames), Buffer(std::move(buffer)) {
133+ }
134+
135+ bool SerializedLocalizationProducer::initializeImpl () {
114136 auto base =
115137 reinterpret_cast <const unsigned char *>(Buffer.get ()->getBufferStart ());
116138 auto tableOffset = endian::read<offset_type>(base, little);
117139 SerializedTable.reset (SerializedLocalizationTable::Create (
118140 base + tableOffset, base + sizeof (offset_type), base));
141+ return true ;
119142}
120143
121144llvm::StringRef
@@ -128,27 +151,64 @@ SerializedLocalizationProducer::getMessage(swift::DiagID id) const {
128151
129152YAMLLocalizationProducer::YAMLLocalizationProducer (llvm::StringRef filePath,
130153 bool printDiagnosticNames)
131- : LocalizationProducer(printDiagnosticNames) {
154+ : LocalizationProducer(printDiagnosticNames), filePath(filePath) {
155+ }
156+
157+ bool YAMLLocalizationProducer::initializeImpl () {
132158 auto FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN (filePath);
133159 llvm::MemoryBuffer *document = FileBufOrErr->get ();
134160 diag::LocalizationInput yin (document->getBuffer ());
135161 yin >> diagnostics;
136162 unknownIDs = std::move (yin.unknownIDs );
163+ return true ;
137164}
138165
139166llvm::StringRef YAMLLocalizationProducer::getMessage (swift::DiagID id) const {
140167 return diagnostics[(unsigned )id];
141168}
142169
143170void YAMLLocalizationProducer::forEachAvailable (
144- llvm::function_ref<void (swift::DiagID, llvm::StringRef)> callback) const {
171+ llvm::function_ref<void (swift::DiagID, llvm::StringRef)> callback) {
172+ initializeIfNeeded ();
173+ if (getState () == FailedInitialization) {
174+ return ;
175+ }
176+
145177 for (uint32_t i = 0 , n = diagnostics.size (); i != n; ++i) {
146178 auto translation = diagnostics[i];
147179 if (!translation.empty ())
148180 callback (static_cast <swift::DiagID>(i), translation);
149181 }
150182}
151183
184+ std::unique_ptr<LocalizationProducer>
185+ LocalizationProducer::producerFor (llvm::StringRef locale, llvm::StringRef path,
186+ bool printDiagnosticNames) {
187+ std::unique_ptr<LocalizationProducer> producer;
188+ llvm::SmallString<128 > filePath (path);
189+ llvm::sys::path::append (filePath, locale);
190+ llvm::sys::path::replace_extension (filePath, " .db" );
191+
192+ // If the serialized diagnostics file not available,
193+ // fallback to the `YAML` file.
194+ if (llvm::sys::fs::exists (filePath)) {
195+ if (auto file = llvm::MemoryBuffer::getFile (filePath)) {
196+ producer = std::make_unique<diag::SerializedLocalizationProducer>(
197+ std::move (file.get ()), printDiagnosticNames);
198+ }
199+ } else {
200+ llvm::sys::path::replace_extension (filePath, " .yaml" );
201+ // In case of missing localization files, we should fallback to messages
202+ // from `.def` files.
203+ if (llvm::sys::fs::exists (filePath)) {
204+ producer = std::make_unique<diag::YAMLLocalizationProducer>(
205+ filePath.str (), printDiagnosticNames);
206+ }
207+ }
208+
209+ return producer;
210+ }
211+
152212llvm::Optional<uint32_t > LocalizationInput::readID (llvm::yaml::IO &io) {
153213 LocalDiagID diagID;
154214 io.mapRequired (" id" , diagID);
0 commit comments