Skip to content

Commit

Permalink
[Frontend] Switch from YAML to .strings based localization
Browse files Browse the repository at this point in the history
  • Loading branch information
xedin committed Aug 22, 2022
1 parent 799fff6 commit 5a164c5
Show file tree
Hide file tree
Showing 14 changed files with 127 additions and 117 deletions.
2 changes: 1 addition & 1 deletion lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1450,7 +1450,7 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
// for the specified locale code.
llvm::SmallString<128> localizationPath(A->getValue());
llvm::sys::path::append(localizationPath, Opts.LocalizationCode);
llvm::sys::path::replace_extension(localizationPath, ".yaml");
llvm::sys::path::replace_extension(localizationPath, ".strings");
if (!llvm::sys::fs::exists(localizationPath)) {
Diags.diagnose(SourceLoc(), diag::warning_cannot_find_locale_file,
Opts.LocalizationCode, localizationPath);
Expand Down
7 changes: 4 additions & 3 deletions localization/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ add_custom_command(
COMMAND
${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/diagnostics/ ${CMAKE_BINARY_DIR}/share/swift/diagnostics/
COMMAND
"${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/swift-def-to-yaml-converter"
"${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/swift-def-to-strings-converter"
--output-directory ${CMAKE_BINARY_DIR}/share/swift/diagnostics/
COMMAND
"${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/swift-serialize-diagnostics"
--input-file-path ${CMAKE_BINARY_DIR}/share/swift/diagnostics/en.yaml
--input-file-path ${CMAKE_BINARY_DIR}/share/swift/diagnostics/en.strings
--output-directory ${CMAKE_BINARY_DIR}/share/swift/diagnostics/
COMMAND
${CMAKE_COMMAND} -E touch ${diagnostic_witness}
DEPENDS
swift-def-to-yaml-converter
swift-def-to-strings-converter
swift-serialize-diagnostics
# Add files in diagnostics subdirectory when they're created
)
Expand All @@ -31,4 +31,5 @@ swift_install_in_component(
FILES_MATCHING
PATTERN "*.db"
PATTERN "*.yaml"
PATTERN "*.strings"
)
25 changes: 25 additions & 0 deletions test/diagnostics/Localization/Inputs/en.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
*--- en.strings - Localized diagnostic messages for English --------------===*
*
* This source file is part of the Swift.org open source project
*
* Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
* Licensed under Apache License v2.0 with Runtime Library Exception
*
* See https://swift.org/LICENSE.txt for license information
* See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
*
*===----------------------------------------------------------------------===*
*
* This file defines the diagnostic messages for the English language.
* Each diagnostic is described in the following format:
* "<diagnostic-id>" = "<diagnostic-message>";
*
*===----------------------------------------------------------------------===*
*
*/
"lex_unterminated_string" = "unterminated string literal";
"var_init_self_referential" = "variable used within its own initial value";
/* Tests different number of spaces between id and diagnostic message */
"cannot_find_in_scope"= "cannot %select{find|find operator}1 %0 in scope";
"warning_invalid_locale_code" = "unsupported locale code; supported locale codes are '%0'";
30 changes: 0 additions & 30 deletions test/diagnostics/Localization/Inputs/en.yaml

This file was deleted.

27 changes: 27 additions & 0 deletions test/diagnostics/Localization/Inputs/fr.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
*===--- fr.strings - Localized diagnostic messages for French ------------===*
*
* This source file is part of the Swift.org open source project
*
* Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
* Licensed under Apache License v2.0 with Runtime Library Exception
*
* See https://swift.org/LICENSE.txt for license information
* See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
*
*===----------------------------------------------------------------------===*
*
* This file defines the diagnostic messages for the French language.
* Each diagnostic is described in the following format:
* "<diagnostic-id>" = "<diagnostic-message>";
*
*/

/* Different order from `en.strings` */
"var_init_self_referential" = "variable utilisée dans sa propre valeur initiale";

"lex_unterminated_string" = "chaîne non terminée littérale";

"cannot_find_in_scope" = "impossible %select{de trouver|de trouver opérateur}1 %0 portée";

"warning_invalid_locale_code" = "code de paramètres régionaux non pris en charge; les codes pris en charge sont '%0'";
30 changes: 0 additions & 30 deletions test/diagnostics/Localization/Inputs/fr.yaml

This file was deleted.

4 changes: 2 additions & 2 deletions test/diagnostics/Localization/fr_debug_diagnostic_name.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.yaml --output-directory=%t/
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.yaml --output-directory=%t/
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.strings --output-directory=%t/
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.strings --output-directory=%t/
// RUN: not %target-swift-frontend -debug-diagnostic-names -localization-path %S/Inputs -locale fr -typecheck %s 2>&1 | %FileCheck %s --check-prefix=CHECK_NAMES

_ = "HI!
Expand Down
4 changes: 2 additions & 2 deletions test/diagnostics/Localization/fr_localization.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.yaml --output-directory=%t/
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.yaml --output-directory=%t/
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.strings --output-directory=%t/
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.strings --output-directory=%t/
// RUN: %target-typecheck-verify-swift -localization-path %t -locale fr

_ = "HI!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %target-typecheck-verify-swift -localization-path /Nonexistent_path -locale en

// <unknown>:0: warning: cannot find translations for 'en' at '/Nonexistent_path/en.yaml': no such file
// <unknown>:0: warning: cannot find translations for 'en' at '/Nonexistent_path/en.strings': no such file
// <unknown>:0: warning: specified localization directory '/Nonexistent_path' does not exist, translation is disabled

_ = "HI!
Expand Down
48 changes: 30 additions & 18 deletions tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static llvm::cl::OptionCategory Category("swift-serialize-diagnostics Options");

static llvm::cl::opt<std::string>
InputFilePath("input-file-path",
llvm::cl::desc("Path to the YAML input file"),
llvm::cl::desc("Path to the YAML or `.strings` input file"),
llvm::cl::cat(Category));

static llvm::cl::opt<std::string>
Expand All @@ -60,38 +60,50 @@ int main(int argc, char *argv[]) {
"Swift Serialize Diagnostics Tool\n");

if (!llvm::sys::fs::exists(options::InputFilePath)) {
llvm::errs() << "YAML file not found\n";
llvm::errs() << "diagnostics file not found\n";
return EXIT_FAILURE;
}

YAMLLocalizationProducer yaml(options::InputFilePath);

auto localeCode = llvm::sys::path::filename(options::InputFilePath);
llvm::SmallString<128> SerializedFilePath(options::OutputDirectory);
llvm::sys::path::append(SerializedFilePath, localeCode);
llvm::sys::path::replace_extension(SerializedFilePath, ".db");

SerializedLocalizationWriter Serializer;
yaml.forEachAvailable(
[&Serializer](swift::DiagID id, llvm::StringRef translation) {
Serializer.insert(id, translation);
});

if (llvm::sys::path::extension(options::InputFilePath) == ".yaml") {
YAMLLocalizationProducer yaml(options::InputFilePath);

yaml.forEachAvailable(
[&Serializer](swift::DiagID id, llvm::StringRef translation) {
Serializer.insert(id, translation);
});

// Print out the diagnostics IDs that are available in YAML but not
// available in `.def`
if (!yaml.unknownIDs.empty()) {
llvm::errs() << "These diagnostic IDs are no longer available: '";
llvm::interleave(
yaml.unknownIDs, [&](std::string id) { llvm::errs() << id; },
[&] { llvm::errs() << ", "; });
llvm::errs() << "'\n";
}
} else {
assert(llvm::sys::path::extension(options::InputFilePath) == ".strings");

StringsLocalizationProducer strings(options::InputFilePath);

strings.forEachAvailable(
[&Serializer](swift::DiagID id, llvm::StringRef translation) {
Serializer.insert(id, translation);
});
}

if (Serializer.emit(SerializedFilePath.str())) {
llvm::errs() << "Cannot serialize diagnostic file "
<< options::InputFilePath << '\n';
return EXIT_FAILURE;
}

// Print out the diagnostics IDs that are available in YAML but not available
// in `.def`
if (!yaml.unknownIDs.empty()) {
llvm::errs() << "These diagnostic IDs are no longer available: '";
llvm::interleave(
yaml.unknownIDs, [&](std::string id) { llvm::errs() << id; },
[&] { llvm::errs() << ", "; });
llvm::errs() << "'\n";
}

return EXIT_SUCCESS;
}
2 changes: 1 addition & 1 deletion unittests/Localization/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
add_swift_unittest(swiftLocalizationTests
DefToYAMLConverterTests.cpp
DefToStringsConverterTests.cpp
SerializationTests.cpp)

target_link_libraries(swiftLocalizationTests
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//===--- DefToYAMLConverterTests.cpp -------------------------------------===//
//===--- DefToStringsConverterTests.cpp -----------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -49,22 +49,22 @@ TEST_F(LocalizationTest, MissingLocalizationFiles) {
ASSERT_TRUE(llvm::sys::fs::exists(getDefaultLocalizationPath()));
llvm::SmallString<128> EnglishLocalization(getDefaultLocalizationPath());
llvm::sys::path::append(EnglishLocalization, "en");
llvm::sys::path::replace_extension(EnglishLocalization, ".yaml");
llvm::sys::path::replace_extension(EnglishLocalization, ".strings");
ASSERT_TRUE(llvm::sys::fs::exists(EnglishLocalization));
llvm::sys::path::replace_extension(EnglishLocalization, ".db");
ASSERT_TRUE(llvm::sys::fs::exists(EnglishLocalization));
}

TEST_F(LocalizationTest, ConverterTestMatchDiagnosticMessagesSequentially) {
YAMLLocalizationProducer yaml(YAMLPath);
yaml.forEachAvailable([](swift::DiagID id, llvm::StringRef translation) {
StringsLocalizationProducer strings(DiagsPath);
strings.forEachAvailable([](swift::DiagID id, llvm::StringRef translation) {
llvm::StringRef msg = diagnosticMessages[static_cast<uint32_t>(id)];
ASSERT_EQ(msg, translation);
});
}

TEST_F(LocalizationTest, ConverterTestMatchDiagnosticMessagesRandomly) {
YAMLLocalizationProducer yaml(YAMLPath);
StringsLocalizationProducer strings(DiagsPath);

std::random_device rd;
std::mt19937 gen(rd());
Expand All @@ -74,7 +74,7 @@ TEST_F(LocalizationTest, ConverterTestMatchDiagnosticMessagesRandomly) {
unsigned randomNum = RandNumber(LocalDiagID::NumDiags);
DiagID randomId = static_cast<DiagID>(randomNum);
llvm::StringRef msg = diagnosticMessages[randomNum];
llvm::StringRef translation = yaml.getMessageOr(randomId, "");
llvm::StringRef translation = strings.getMessageOr(randomId, "");
ASSERT_EQ(msg, translation);
}
}
12 changes: 6 additions & 6 deletions unittests/Localization/LocalizationTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ struct LocalizationTest : public ::testing::Test {
llvm::SmallVector<std::string, 4> TempFiles;

public:
std::string YAMLPath;
std::string DiagsPath;

LocalizationTest() {
YAMLPath = std::string(createTemporaryFile("en", "yaml"));
DiagsPath = std::string(createTemporaryFile("en", "strings"));
}

void SetUp() override {
bool failed = convertDefIntoYAML(YAMLPath);
assert(!failed && "failed to generate a YAML file");
bool failed = convertDefIntoStrings(DiagsPath);
assert(!failed && "failed to generate a `.strings` file");
}

void TearDown() override {
Expand All @@ -85,7 +85,7 @@ struct LocalizationTest : public ::testing::Test {
unsigned RandNumber(unsigned n) { return unsigned(rand()) % n; }

protected:
static bool convertDefIntoYAML(std::string outputPath) {
static bool convertDefIntoStrings(std::string outputPath) {
std::error_code error;
llvm::raw_fd_ostream OS(outputPath, error, llvm::sys::fs::OF_None);
if (OS.has_error() || error)
Expand All @@ -95,7 +95,7 @@ struct LocalizationTest : public ::testing::Test {
llvm::ArrayRef<const char *> messages(diagnosticMessages,
LocalDiagID::NumDiags);

DefToYAMLConverter converter(ids, messages);
DefToStringsConverter converter(ids, messages);
converter.convert(OS);

OS.flush();
Expand Down
Loading

0 comments on commit 5a164c5

Please sign in to comment.