Skip to content

Commit 8148434

Browse files
committed
[ ADD ] i18n module alpha complete. Still need to test in production
1 parent b54ab27 commit 8148434

14 files changed

Lines changed: 1002 additions & 0 deletions

File tree

‎i18n/alexa/__init__.py‎

Whitespace-only changes.

‎i18n/alexa/data.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from gettext import gettext as _
2+
3+
WELCOME_MSG = _("Hello! Welcome to Cake walk. What is your birthday?")
4+
WELCOME_REMPROMPT_MSG = _("I was born Nov. 6th, 2014. When were you born?")
5+
WELCOME_BACK_MSG = _(
6+
"Welcome back. It looks like there is {} day until your {}th birthday.")
7+
WELCOME_BACK_MSG_plural = _(
8+
"Welcome back. It looks like there are {} days until your {}th birthday")
9+
HAPPY_BIRTHDAY_MSG = _("Happy {}th birthday!")
10+
REGISTER_BIRTHDAY_MSG = _("Thanks, I'll remember that you were born {} {} {}")
11+
HELP_MSG = _("You can tell me your date of birth and I'll take note. You can also just say, 'register my birthday' and I will guide you. Which one would you like to try?")
12+
GOODBYE_MSG = _("Goodbye!")
13+
ERROR_MSG = _(
14+
"Sorry, I couldn't understand what you said. Can you reformulate?")
15+
ERROR_TIMEZONE_MSG = _(
16+
"I can't determine your timezone. Please check your device settings and make sure a timezone was selected. After that please reopen the skill and try again!")

‎i18n/lambda_function.py‎

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# This sample demonstrates handling intents from an Alexa skill and using the
4+
# Alexa Skills Kid SDK (v2)
5+
# Please visit https://alexa.design/cookbook for additional examples on
6+
# implementing slots, dialog management,
7+
# session persistence, api calls, and more.
8+
9+
import requests
10+
import logging
11+
import calendar
12+
from datetime import datetime
13+
from pytz import timezone
14+
import gettext
15+
16+
from alexa import data
17+
18+
from ask_sdk_s3.adapter import S3Adapter
19+
from ask_sdk_core.skill_builder import CustomSkillBuilder
20+
from ask_sdk_core.dispatch_components import (
21+
AbstractRequestHandler, AbstractExceptionHandler,
22+
AbstractRequestInterceptor, AbstractResponseInterceptor
23+
)
24+
from ask_sdk_core.utils import is_request_type, is_intent_name
25+
26+
s3_adapter = S3Adapter(bucket_name="custom-walk-testing")
27+
sb = CustomSkillBuilder(persistence_adapter=s3_adapter)
28+
29+
logger = logging.getLogger("main")
30+
logger.setLevel(logging.INFO)
31+
32+
33+
class LaunchRequestIntentHandler(AbstractRequestHandler):
34+
"""
35+
Handler for Skill Launch
36+
"""
37+
38+
def can_handle(self, handler_input):
39+
return is_request_type("LaunchRequest")(handler_input)
40+
41+
def handle(self, handler_input):
42+
_ = handler_input.attributes_manager.request_attributes["_"]
43+
44+
speech = _(data.WELCOME_MSG)
45+
reprompt = _(data.WELCOME_REMPROMPT_MSG)
46+
47+
handler_input.response_builder.speak(speech).ask(reprompt)
48+
return handler_input.response_builder.response
49+
50+
51+
class HasBirthdayLaunchRequestHandler(AbstractRequestHandler):
52+
"""
53+
Handler for launch after they have set their birthday
54+
"""
55+
56+
def can_handle(self, handler_input):
57+
# extract persistent attributes and check if they are all present
58+
attr = handler_input.attributes_manager.persistent_attributes
59+
attributes_are_present = (
60+
"year" in attr and "month" in attr and "day" in attr)
61+
62+
return attributes_are_present and is_request_type("LaunchRequest")(handler_input)
63+
64+
def handle(self, handler_input):
65+
_ = handler_input.attributes_manager.request_attributes["_"]
66+
67+
attr = handler_input.attributes_manager.persistent_attributes
68+
69+
year = int(attr['year'])
70+
# month is a string, and we need to convert it to a month index later
71+
month = attr['month']
72+
day = int(attr['day'])
73+
74+
# get device id / timezones
75+
sys_object = handler_input.request_envelope.context.system
76+
77+
# get systems api information
78+
api_endpoint = sys_object.api_endpoint
79+
device_id = sys_object.device.device_id
80+
api_access_token = sys_object.api_access_token
81+
82+
# construct systems api timezone url
83+
url = '{api_endpoint}/v2/devices/{device_id}/settings/System.timeZone'.format(
84+
api_endpoint=api_endpoint, device_id=device_id)
85+
headers = {'Authorization': 'Bearer ' + api_access_token}
86+
87+
userTimeZone = ""
88+
try:
89+
r = requests.get(url, headers=headers)
90+
res = r.json()
91+
logger.info("Device API result: {}".format(str(res)))
92+
userTimeZone = res
93+
except Exception:
94+
speech = _(data.ERROR_TIMEZONE_MSG)
95+
handler_input.response_builder.speak(speech)
96+
return handler_input.response_builder.response
97+
98+
# getting the current date with the time
99+
now_time = datetime.now(timezone(userTimeZone))
100+
101+
# Removing the time from the date because it affects our difference calculation
102+
now_date = datetime(now_time.year, now_time.month, now_time.day)
103+
current_year = now_time.year
104+
105+
# getting the next birthday
106+
month_as_index = list(calendar.month_abbr).index(month[:3])
107+
next_birthday = datetime(current_year, month_as_index, day)
108+
109+
# check if we need to adjust bday by one year
110+
if now_date > next_birthday:
111+
next_birthday = datetime(
112+
current_year + 1,
113+
month_as_index,
114+
day
115+
)
116+
current_year += 1
117+
# setting the default speak_output to Happy xth Birthday!!
118+
# alexa will automatically correct the oridinal for you.
119+
# no need to worry about when to use st, th, rd
120+
speak_output = _(data.HAPPY_BIRTHDAY_MSG).format(
121+
str(current_year - year))
122+
if now_date != next_birthday:
123+
diff_days = abs((now_date - next_birthday).days)
124+
logger.info(speak_output)
125+
speak_output = _(data.WELCOME_BACK_MSG).format(
126+
diff_days,
127+
(current_year-year)
128+
)
129+
if(diff_days != 1):
130+
speak_output = _(data.WELCOME_BACK_MSG_plural).format(
131+
diff_days,
132+
(current_year-year)
133+
)
134+
135+
handler_input.response_builder.speak(speak_output)
136+
return handler_input.response_builder.response
137+
138+
139+
class BirthdayIntentHandler(AbstractRequestHandler):
140+
"""
141+
Handler for Capturing the Birthday
142+
"""
143+
144+
def can_handle(self, handler_input):
145+
return is_intent_name("CaptureBirthdayIntent")(handler_input)
146+
147+
def handle(self, handler_input):
148+
_ = handler_input.attributes_manager.request_attributes["_"]
149+
slots = handler_input.request_envelope.request.intent.slots
150+
151+
# extract slot values
152+
year = slots["year"].value
153+
month = slots["month"].value
154+
day = slots["day"].value
155+
156+
# save slots into session attributes
157+
session_attr = handler_input.attributes_manager.session_attributes
158+
session_attr['year'] = year
159+
session_attr['month'] = month
160+
session_attr['day'] = day
161+
162+
# save session attributes as persistent attributes
163+
handler_input.attributes_manager.persistent_attributes = session_attr
164+
handler_input.attributes_manager.save_persistent_attributes()
165+
166+
speech = _(data.REGISTER_BIRTHDAY_MSG).format(month, day, year)
167+
handler_input.response_builder.speak(speech)
168+
return handler_input.response_builder.response
169+
170+
171+
class HelpIntentHandler(AbstractRequestHandler):
172+
"""
173+
Handler for AMAZON.HelpIntent
174+
"""
175+
176+
def can_handle(self, handler_input):
177+
return is_intent_name("AMAZON.HelpIntent")(handler_input)
178+
179+
def handle(self, handler_input):
180+
_ = handler_input.attributes_manager.request_attributes["_"]
181+
speak_output = _(data.HELP_MSG)
182+
183+
handler_input.response_builder.speak(
184+
speak_output
185+
).ask(speak_output)
186+
return handler_input.response_builder.response
187+
188+
189+
class CatchAllExceptionHandler(AbstractExceptionHandler):
190+
"""
191+
Catch all exception handler, log exception and
192+
respond with custom message.
193+
"""
194+
195+
def can_handle(self, handler_input, exception):
196+
return True
197+
198+
def handle(self, handler_input, exception):
199+
logger.info(exception)
200+
_ = handler_input.attributes_manager.request_attributes["_"]
201+
speak_output = _(data.ERROR_MSG)
202+
handler_input.response_builder.speak(speak_output).ask(speak_output)
203+
return handler_input.response_builder.response
204+
205+
206+
class CancelAndStopIntentHandler(AbstractRequestHandler):
207+
"""
208+
Handler for AMAZON.CancelIntent and AMAZON.StopIntent
209+
"""
210+
211+
def can_handle(self, handler_input):
212+
return is_intent_name("AMAZON.CancelIntent")(handler_input) \
213+
and is_intent_name("AMAZON.StopIntent")(handler_input)
214+
215+
def handle(self, handler_input):
216+
_ = handler_input.attributes_manager.request_attributes["_"]
217+
speak_output = _(data.GOODBYE_MSG)
218+
handler_input.response_builder.speak(speak_output)
219+
return handler_input.response_builder.response
220+
221+
222+
class SessionEndedRequestHandler(AbstractRequestHandler):
223+
"""
224+
Handler for SessionEndedRequest
225+
"""
226+
227+
def can_handle(self, handler_input):
228+
return is_request_type("SessionEndedRequest")(handler_input)
229+
230+
def handle(self, handler_input):
231+
# Any cleanup logic goes here
232+
return handler_input.response_builder.response
233+
234+
235+
class CacheSpeechForRepeatInterceptor(AbstractResponseInterceptor):
236+
"""Cache the output speech and reprompt to session attributes,
237+
for repeat intent.
238+
"""
239+
240+
def process(self, handler_input, response):
241+
# type: (HandlerInput, Response) -> None
242+
session_attr = handler_input.attributes_manager.session_attributes
243+
session_attr["speech"] = response.output_speech
244+
session_attr["reprompt"] = response.reprompt
245+
246+
247+
class LocalizationInterceptor(AbstractRequestInterceptor):
248+
"""
249+
Add function to request attributes, that can load locale specific data.
250+
"""
251+
252+
def process(self, handler_input):
253+
locale = handler_input.request_envelope.request.locale
254+
logger.info("Locale is {}".format(locale))
255+
i18n = gettext.translation(
256+
'data', localedir='locales', languages=[locale], fallback=True)
257+
handler_input.attributes_manager.request_attributes["_"] = i18n.gettext
258+
259+
260+
# register request / intent handlers
261+
sb.add_request_handler(HasBirthdayLaunchRequestHandler())
262+
sb.add_request_handler(LaunchRequestIntentHandler())
263+
sb.add_request_handler(BirthdayIntentHandler())
264+
sb.add_request_handler(HelpIntentHandler())
265+
sb.add_request_handler(CancelAndStopIntentHandler())
266+
sb.add_request_handler(SessionEndedRequestHandler())
267+
268+
# register exception handlers
269+
sb.add_exception_handler(CatchAllExceptionHandler())
270+
271+
# register localization interceptor and cache interceptor
272+
sb.add_global_request_interceptor(LocalizationInterceptor())
273+
sb.add_global_response_interceptor(CacheSpeechForRepeatInterceptor())
274+
275+
lambda_handler = sb.lambda_handler()

‎i18n/locales/data.pot‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# SOME DESCRIPTIVE TITLE.
2+
# Copyright (C) YEAR ORGANIZATION
3+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: PACKAGE VERSION\n"
8+
"POT-Creation-Date: 2019-10-02 17:11-0400\n"
9+
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
11+
"Language-Team: LANGUAGE <LL@li.org>\n"
12+
"MIME-Version: 1.0\n"
13+
"Content-Type: text/plain; charset=cp1252\n"
14+
"Content-Transfer-Encoding: 8bit\n"
15+
"Generated-By: pygettext.py 1.5\n"
16+
17+
18+
#: alexa\data.py:3
19+
msgid "Hello! Welcome to Cake walk. What is your birthday?"
20+
msgstr ""
21+
22+
#: alexa\data.py:4
23+
msgid "I was born Nov. 6th, 2014. When were you born?"
24+
msgstr ""
25+
26+
#: alexa\data.py:5
27+
msgid "Welcome back. It looks like there is {} day until your {}th birthday."
28+
msgstr ""
29+
30+
#: alexa\data.py:7
31+
msgid "Welcome back. It looks like there are {} days until your {}th birthday"
32+
msgstr ""
33+
34+
#: alexa\data.py:9
35+
msgid "Happy {}th birthday!"
36+
msgstr ""
37+
38+
#: alexa\data.py:10
39+
msgid "Thanks, I'll remember that you were born {} {} {}"
40+
msgstr ""
41+
42+
#: alexa\data.py:11
43+
msgid "You can tell me your date of birth and I'll take note. You can also just say, 'register my birthday' and I will guide you. Which one would you like to try?"
44+
msgstr ""
45+
46+
#: alexa\data.py:12
47+
msgid "Goodbye!"
48+
msgstr ""
49+
50+
#: alexa\data.py:13
51+
msgid "Sorry, I couldn't understand what you said. Can you reformulate?"
52+
msgstr ""
53+
54+
#: alexa\data.py:15
55+
msgid "I can't determine your timezone. Please check your device settings and make sure a timezone was selected. After that please reopen the skill and try again!"
56+
msgstr ""
57+
359 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)