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
|
# File 'app/workers/restaurant_tags/ai_help_title_tag_worker.rb', line 5
def perform(restaurant_tag_id, translation_id = nil)
store_processing_status(translation_id) if translation_id.present?
restaurant_tag = RestaurantTag.find_by(id: restaurant_tag_id)
if restaurant_tag.nil?
error_msg = "RestaurantTag with ID #{restaurant_tag_id} not found."
store_error_status(translation_id, error_msg) if translation_id.present?
raise error_msg
elsif restaurant_tag.title_en.blank?
error_msg = "RestaurantTag with ID #{restaurant_tag_id} does not have a valid title_en."
store_error_status(translation_id, error_msg) if translation_id.present?
raise error_msg
end
prefix = restaurant_tag.title_en.split(':').first.strip
last_word = restaurant_tag.title_en.split(':').last.strip
target_locales = MyLocaleManager::AVAILABLE_LOCALES.reject { |locale| locale == :en }
language_map = {
th: 'Thai',
cn: 'Traditional Chinese (Taiwan/Hong Kong)',
es: 'Spanish',
fr: 'French',
de: 'German',
ru: 'Russian',
ms: 'Malay',
ko: 'Korean',
ja: 'Japanese',
id: 'Indonesian',
vi: 'Vietnamese',
zh: 'Simplified Chinese (Mainland China)',
}
language_list = target_locales.map { |locale| "#{locale}: #{language_map[locale]}" }.join("\n ")
json_keys = target_locales.map do |locale|
"\"title_#{locale}\": \"Translated #{language_map[locale]} title\""
end.join(",\n ")
prompt = <<~PROMPT
Hungry Hub is an online reservation application for the best restaurant offers in Thailand.
Hungry Hub has restaurant tags, which are keywords or short labels used to describe or categorize the type of cuisine, dining style, popular zone, shopping mall, BTS, MRT, Location, Facilities, Admin, Hashtag, Occasion, and Offer.
These tags help customers quickly understand the restaurant's concept or theme and make it easier to find.
Context: A single keyword label used to classify restaurants (e.g., "Seafood", "Vegan", "Fine Dining"). Appears in filters and search tags.
You are a language specialist helping translate and generate titles for restaurant tags.
Please help translate the following title into ALL these languages, using appropriate, natural phrasing for each:
#{language_list}
The text "#{last_word}" is the text I need you to translate.
Provide translations for ALL languages listed above.
Ensure that your response follows this JSON format exactly:
{
#{json_keys}
}
Important:
- Provide ALL translations in a single JSON response
- Use natural, culturally appropriate phrasing for each language
- Maintain the same meaning and tone across all translations
- For location names (BTS, MRT, Shopping Mall, Popular Zone), you may transliterate or keep the original name if more appropriate
PROMPT
faraday = OpenrouterClient.create_connection
response = Retriable.retriable(
tries: 3,
base_interval: 1,
multiplier: 2,
on: [Faraday::TimeoutError, Faraday::ConnectionFailed],
) do
faraday.post('/api/v1/chat/completions') do |req|
req.['HTTP-Referer'] = 'https://hungryhub.com'
req.['X-Title'] = 'HungryHub Restaurant Tag Translation'
estimated_tokens = (last_word.length / 2) + (last_word.length * target_locales.size * 2)
max_tokens = [estimated_tokens, 8000].max.to_i
req.body = {
model: 'anthropic/claude-3.5-sonnet',
messages: [
{ role: 'user', content: prompt },
],
temperature: 0.3,
max_tokens: max_tokens,
}.to_json
end
end
if response.success?
response_data = JSON.parse(response.body)
json_string = response_data['choices'][0]['message']['content']
json_match = json_string.match(/\{.*\}/m)
if json_match
json_string = json_match[0]
json_data = JSON.parse(json_string)
update_hash = {}
target_locales.each do |locale|
key = "title_#{locale}"
if json_data[key].present?
update_hash[key.to_sym] = "#{prefix}:#{json_data[key]}"
end
end
if update_hash.present?
restaurant_tag.update(update_hash)
BUSINESS_LOGGER.info(
'AI translation completed for restaurant tag',
{
restaurant_tag_id: restaurant_tag_id,
translated_locales: update_hash.keys,
source_text: last_word,
translation_id: translation_id,
},
)
store_success_status(translation_id, update_hash) if translation_id.present?
else
error_msg = 'Error: No valid translations found in the response'
store_error_status(translation_id, error_msg) if translation_id.present?
raise error_msg
end
else
error_msg = "Error: No valid JSON found in the response, response: #{json_string}"
store_error_status(translation_id, error_msg) if translation_id.present?
raise error_msg
end
else
error_msg = "HTTP error occurred: #{response.status} - #{response.body}"
store_error_status(translation_id, error_msg) if translation_id.present?
raise error_msg
end
rescue StandardError => e
APMErrorHandler.report(e, context: { restaurant_tag_id: restaurant_tag_id, translation_id: translation_id })
store_error_status(translation_id, e.message) if translation_id.present?
raise
end
|