Skip to content

Commit 1fdb5cc

Browse files
committed
Add placeholder handling in Google Translate translate
1 parent 7447e69 commit 1fdb5cc

File tree

4 files changed

+100
-5
lines changed

4 files changed

+100
-5
lines changed

cli/src/services/formatters/hook-runner.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Vendor
22
import * as chalk from 'chalk';
3-
import decamelize from 'decamelize';
3+
import * as decamelize from 'decamelize';
44

55
const capitalizeFirstLetter = (str: string) =>
66
str.charAt(0).toUpperCase() + str.slice(1);

lib/machine_translations/provider/google_translate.ex

+21-3
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,23 @@ defmodule Accent.MachineTranslations.Provider.GoogleTranslate do
127127
def enabled?(_), do: false
128128

129129
def translate(provider, contents, source, target) do
130+
contents_with_no_translate = Enum.map(contents, &mark_no_translate/1)
131+
130132
with {:ok, {source, target}} <-
131133
Accent.MachineTranslations.map_source_and_target(
132134
source,
133135
target,
134136
@supported_languages
135137
),
136138
params = %{
137-
contents: contents,
138-
mimeType: "text/plain",
139+
contents: contents_with_no_translate,
140+
mimeType: "text/html",
139141
sourceLanguageCode: source,
140142
targetLanguageCode: target
141143
},
142144
{:ok, %{body: %{"translations" => translations}}} <-
143145
Tesla.post(client(provider.config), ":translateText", params) do
144-
{:ok, Enum.map(translations, &%TranslatedText{text: &1["translatedText"]})}
146+
{:ok, Enum.map(translations, &%TranslatedText{text: unmark_no_translate(&1["translatedText"])})}
145147
else
146148
{:ok, %{status: status, body: body}} when status > 201 ->
147149
{:error, body}
@@ -151,6 +153,22 @@ defmodule Accent.MachineTranslations.Provider.GoogleTranslate do
151153
end
152154
end
153155

156+
defp mark_no_translate(value) do
157+
Enum.find_value(Langue.placeholder_regex(), fn regex ->
158+
matches = Regex.scan(regex, value)
159+
160+
if Enum.any?(matches) do
161+
Enum.reduce(List.flatten(matches), value, fn match, value ->
162+
String.replace(value, match, ~s(<span translate="no">#{match}</span>))
163+
end)
164+
end
165+
end) || value
166+
end
167+
168+
defp unmark_no_translate(value) do
169+
String.replace(value, ~r/<span translate="no">([^<]+)<\/span>/, "\\1")
170+
end
171+
154172
defmodule Auth do
155173
@moduledoc false
156174
@behaviour Tesla.Middleware

mix.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
9797
"telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},
9898
"telemetry_ui": {:hex, :telemetry_ui, "4.1.0", "d69be6a89fd78c7030011363dbed735afb558a925dac24ee2615aae588375d9e", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, "~> 2.13", [hex: :oban, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_ecto, "~> 4.4", [hex: :phoenix_ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.0", [hex: :telemetry_poller, repo: "hexpm", optional: false]}, {:timex, "~> 3.7", [hex: :timex, repo: "hexpm", optional: false]}, {:vega_lite, "~> 0.1", [hex: :vega_lite, repo: "hexpm", optional: false]}, {:vega_lite_convert, "~> 0.6", [hex: :vega_lite_convert, repo: "hexpm", optional: true]}, {:vix, "~> 0.16", [hex: :vix, repo: "hexpm", optional: true]}], "hexpm", "6e5af411bdc7bbd4ab88294c4f58391ce7ec6cba7119fcb3799e2ec2de7104fa"},
99-
"tesla": {:hex, :tesla, "1.7.0", "a62dda2f80d4f8a925eb7b8c5b78c461e0eb996672719fe1a63b26321a5f8b4e", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "2e64f01ebfdb026209b47bc651a0e65203fcff4ae79c11efb73c4852b00dc313"},
99+
"tesla": {:hex, :tesla, "1.8.0", "d511a4f5c5e42538d97eef7c40ec4f3e44effdc5068206f42ed859e09e51d1fd", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "10501f360cd926a309501287470372af1a6e1cbed0f43949203a4c13300bc79f"},
100100
"timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
101101
"toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"},
102102
"tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
defmodule AccentTest.MachineTranslations do
2+
@moduledoc false
3+
use ExUnit.Case, async: false
4+
5+
import Tesla.Mock
6+
7+
alias Accent.MachineTranslations
8+
9+
describe "translate/2" do
10+
test "google_translate" do
11+
mock_global(fn
12+
%{body: body, url: "https://translation.googleapis.com/v3/projects/1234/:translateText"} ->
13+
assert Jason.decode!(body) === %{
14+
"contents" => ["Test"],
15+
"mimeType" => "text/html",
16+
"sourceLanguageCode" => "fr",
17+
"targetLanguageCode" => "en"
18+
}
19+
20+
%Tesla.Env{status: 200, body: %{"translations" => [%{"translatedText" => "Translated"}]}}
21+
end)
22+
23+
entries = [%Langue.Entry{value: "Test", value_type: "string", key: "."}]
24+
source_language = %{slug: "fr"}
25+
target_language = %{slug: "en"}
26+
provider_config = %{"key" => Jason.encode!(%{"project_id" => "1234", "type" => "service_account"})}
27+
config = %{"provider" => "google_translate", "config" => provider_config}
28+
29+
[entry] = MachineTranslations.translate(entries, source_language, target_language, config)
30+
assert entry.value === "Translated"
31+
end
32+
33+
test "google_translate no translate span" do
34+
mock_global(fn
35+
%{body: body, url: "https://translation.googleapis.com/v3/projects/1234/:translateText"} ->
36+
assert Jason.decode!(body) === %{
37+
"contents" => [~s(Test <span translate="no">%{placeholder}</span> bla)],
38+
"mimeType" => "text/html",
39+
"sourceLanguageCode" => "fr",
40+
"targetLanguageCode" => "en"
41+
}
42+
43+
%Tesla.Env{
44+
status: 200,
45+
body: %{
46+
"translations" => [%{"translatedText" => ~s(Translated <span translate="no">%{placeholder}</span> bla)}]
47+
}
48+
}
49+
end)
50+
51+
entries = [%Langue.Entry{value: "Test %{placeholder} bla", value_type: "string", key: "."}]
52+
source_language = %{slug: "fr"}
53+
target_language = %{slug: "en"}
54+
provider_config = %{"key" => Jason.encode!(%{"project_id" => "1234", "type" => "service_account"})}
55+
config = %{"provider" => "google_translate", "config" => provider_config}
56+
57+
[entry] = MachineTranslations.translate(entries, source_language, target_language, config)
58+
assert entry.value === "Translated %{placeholder} bla"
59+
end
60+
61+
test "google_translate error" do
62+
mock_global(fn
63+
%{url: "https://translation.googleapis.com/v3/projects/1234/:translateText"} ->
64+
%Tesla.Env{status: 400, body: "Something"}
65+
end)
66+
67+
entries = [%Langue.Entry{value: "Test", value_type: "string", key: "."}]
68+
source_language = %{slug: "fr"}
69+
target_language = %{slug: "en"}
70+
provider_config = %{"key" => Jason.encode!(%{"project_id" => "1234", "type" => "service_account"})}
71+
config = %{"provider" => "google_translate", "config" => provider_config}
72+
73+
{:error, error} = MachineTranslations.translate(entries, source_language, target_language, config)
74+
assert error === "Something"
75+
end
76+
end
77+
end

0 commit comments

Comments
 (0)