diff --git a/homeassistant/components/config_entry_example/.translations/en.json b/homeassistant/components/config_entry_example/.translations/en.json new file mode 100644 index 00000000000..ec24d01ebc8 --- /dev/null +++ b/homeassistant/components/config_entry_example/.translations/en.json @@ -0,0 +1,24 @@ +{ + "config": { + "error": { + "invalid_object_id": "Invalid object ID" + }, + "step": { + "init": { + "data": { + "object_id": "Object ID" + }, + "description": "Please enter an object_id for the test entity.", + "title": "Pick object id" + }, + "name": { + "data": { + "name": "Name" + }, + "description": "Please enter a name for the test entity.", + "title": "Name of the entity" + } + }, + "title": "Config Entry Example" + } +} \ No newline at end of file diff --git a/homeassistant/components/config_entry_example.py b/homeassistant/components/config_entry_example/__init__.py similarity index 90% rename from homeassistant/components/config_entry_example.py rename to homeassistant/components/config_entry_example/__init__.py index 2d5ea728ff3..3ebfdc3a183 100644 --- a/homeassistant/components/config_entry_example.py +++ b/homeassistant/components/config_entry_example/__init__.py @@ -62,13 +62,11 @@ class ExampleConfigFlow(config_entries.ConfigFlowHandler): return (yield from self.async_step_name()) errors = { - 'object_id': 'Invalid object id.' + 'object_id': 'invalid_object_id' } return self.async_show_form( - title='Pick object id', step_id='init', - description="Please enter an object_id for the test entity.", data_schema=vol.Schema({ 'object_id': str }), @@ -92,9 +90,7 @@ class ExampleConfigFlow(config_entries.ConfigFlowHandler): ) return self.async_show_form( - title='Name of the entity', step_id='name', - description="Please enter a name for the test entity.", data_schema=vol.Schema({ 'name': str }), diff --git a/homeassistant/components/config_entry_example/strings.json b/homeassistant/components/config_entry_example/strings.json new file mode 100644 index 00000000000..a7a8cd4025b --- /dev/null +++ b/homeassistant/components/config_entry_example/strings.json @@ -0,0 +1,24 @@ +{ + "config": { + "title": "Config Entry Example", + "step": { + "init": { + "title": "Pick object id", + "description": "Please enter an object_id for the test entity.", + "data": { + "object_id": "Object ID" + } + }, + "name": { + "title": "Name of the entity", + "description": "Please enter a name for the test entity.", + "data": { + "name": "Name" + } + } + }, + "error": { + "invalid_object_id": "Invalid object ID" + } + } +} diff --git a/homeassistant/components/hue/.translations/en.json b/homeassistant/components/hue/.translations/en.json new file mode 100644 index 00000000000..ee2e01fdb17 --- /dev/null +++ b/homeassistant/components/hue/.translations/en.json @@ -0,0 +1,26 @@ +{ + "config": { + "abort": { + "all_configured": "All Philips Hue bridges are already configured", + "discover_timeout": "Unable to discover Hue bridges", + "no_bridges": "No Philips Hue bridges discovered" + }, + "error": { + "linking": "Unknown linking error occurred.", + "register_failed": "Failed to register, please try again" + }, + "step": { + "init": { + "data": { + "host": "Host" + }, + "title": "Pick Hue bridge" + }, + "link": { + "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)", + "title": "Link Hub" + } + }, + "title": "Philips Hue Bridge" + } +} diff --git a/homeassistant/components/hue.py b/homeassistant/components/hue/__init__.py similarity index 95% rename from homeassistant/components/hue.py rename to homeassistant/components/hue/__init__.py index d3870f0a3a1..92b23a74065 100644 --- a/homeassistant/components/hue.py +++ b/homeassistant/components/hue/__init__.py @@ -304,12 +304,12 @@ class HueFlowHandler(config_entries.ConfigFlowHandler): bridges = await discover_nupnp(websession=self._websession) except asyncio.TimeoutError: return self.async_abort( - reason='Unable to discover Hue bridges.' + reason='discover_timeout' ) if not bridges: return self.async_abort( - reason='No Philips Hue bridges discovered.' + reason='no_bridges' ) # Find already configured hosts @@ -322,7 +322,7 @@ class HueFlowHandler(config_entries.ConfigFlowHandler): if not hosts: return self.async_abort( - reason='All Philips Hue bridges are already configured.' + reason='all_configured' ) elif len(hosts) == 1: @@ -331,7 +331,6 @@ class HueFlowHandler(config_entries.ConfigFlowHandler): return self.async_show_form( step_id='init', - title='Pick Hue Bridge', data_schema=vol.Schema({ vol.Required('host'): vol.In(hosts) }) @@ -352,10 +351,10 @@ class HueFlowHandler(config_entries.ConfigFlowHandler): await bridge.initialize() except (asyncio.TimeoutError, aiohue.RequestError, aiohue.LinkButtonNotPressed): - errors['base'] = 'Failed to register, please try again.' + errors['base'] = 'register_failed' except aiohue.AiohueException: - errors['base'] = 'Unknown linking error occurred.' - _LOGGER.exception('Uknown Hue linking error occurred') + errors['base'] = 'linking' + _LOGGER.exception('Unknown Hue linking error occurred') else: return self.async_create_entry( title=bridge.config.name, @@ -368,8 +367,6 @@ class HueFlowHandler(config_entries.ConfigFlowHandler): return self.async_show_form( step_id='link', - title='Link Hub', - description=CONFIG_INSTRUCTIONS, errors=errors, ) diff --git a/homeassistant/components/hue/strings.json b/homeassistant/components/hue/strings.json new file mode 100644 index 00000000000..59b1ecd3cd1 --- /dev/null +++ b/homeassistant/components/hue/strings.json @@ -0,0 +1,26 @@ +{ + "config": { + "title": "Philips Hue Bridge", + "step": { + "init": { + "title": "Pick Hue bridge", + "data": { + "host": "Host" + } + }, + "link": { + "title": "Link Hub", + "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" + } + }, + "error": { + "register_failed": "Failed to register, please try again", + "linking": "Unknown linking error occurred." + }, + "abort": { + "discover_timeout": "Unable to discover Hue bridges", + "no_bridges": "No Philips Hue bridges discovered", + "all_configured": "All Philips Hue bridges are already configured" + } + } +} diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index 230e48f0cec..eb05e800683 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -442,7 +442,7 @@ class FlowManager: 'Handler returned incorrect type: {}'.format(result['type'])) if result['type'] == RESULT_TYPE_FORM: - flow.cur_step = (result.pop('step_id'), result['data_schema']) + flow.cur_step = (result['step_id'], result['data_schema']) return result # Abort and Success results both finish the flow @@ -468,6 +468,7 @@ class ConfigFlowHandler: # Set by flow manager flow_id = None hass = None + domain = None source = SOURCE_USER cur_step = None @@ -475,15 +476,13 @@ class ConfigFlowHandler: # VERSION @callback - def async_show_form(self, *, title, step_id, description=None, - data_schema=None, errors=None): + def async_show_form(self, *, step_id, data_schema=None, errors=None): """Return the definition of a form to gather user input.""" return { 'type': RESULT_TYPE_FORM, 'flow_id': self.flow_id, - 'title': title, + 'domain': self.domain, 'step_id': step_id, - 'description': description, 'data_schema': data_schema, 'errors': errors, } @@ -494,6 +493,7 @@ class ConfigFlowHandler: return { 'type': RESULT_TYPE_CREATE_ENTRY, 'flow_id': self.flow_id, + 'domain': self.domain, 'title': title, 'data': data, } @@ -504,5 +504,6 @@ class ConfigFlowHandler: return { 'type': RESULT_TYPE_ABORT, 'flow_id': self.flow_id, + 'domain': self.domain, 'reason': reason } diff --git a/script/translations_develop b/script/translations_develop new file mode 100755 index 00000000000..eb9d685fa8e --- /dev/null +++ b/script/translations_develop @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Compile the current translation strings files for testing + +# Safe bash settings +# -e Exit on command fail +# -u Exit on unset variable +# -o pipefail Exit if piped command has error code +set -eu -o pipefail + +cd "$(dirname "$0")/.." + +mkdir -p build/translations-download + +script/translations_upload_merge.py + +# Use the generated translations upload file as the mock output from the +# Lokalise download +mv build/translations-upload.json build/translations-download/en.json + +script/translations_download_split.py diff --git a/tests/components/config/test_config_entries.py b/tests/components/config/test_config_entries.py index 1551ba74319..84667b8704b 100644 --- a/tests/components/config/test_config_entries.py +++ b/tests/components/config/test_config_entries.py @@ -101,9 +101,7 @@ def test_initialize_flow(hass, client): schema[vol.Required('password')] = str return self.async_show_form( - title='test-title', step_id='init', - description='test-description', data_schema=schema, errors={ 'username': 'Should be unique.' @@ -121,8 +119,8 @@ def test_initialize_flow(hass, client): assert data == { 'type': 'form', - 'title': 'test-title', - 'description': 'test-description', + 'domain': 'test', + 'step_id': 'init', 'data_schema': [ { 'name': 'username', @@ -157,6 +155,7 @@ def test_abort(hass, client): data = yield from resp.json() data.pop('flow_id') assert data == { + 'domain': 'test', 'reason': 'bla', 'type': 'abort' } @@ -186,6 +185,7 @@ def test_create_account(hass, client): data = yield from resp.json() data.pop('flow_id') assert data == { + 'domain': 'test', 'title': 'Test Entry', 'type': 'create_entry' } @@ -203,7 +203,6 @@ def test_two_step_flow(hass, client): @asyncio.coroutine def async_step_init(self, user_input=None): return self.async_show_form( - title='test-title', step_id='account', data_schema=vol.Schema({ 'user_title': str @@ -224,8 +223,8 @@ def test_two_step_flow(hass, client): flow_id = data.pop('flow_id') assert data == { 'type': 'form', - 'title': 'test-title', - 'description': None, + 'domain': 'test', + 'step_id': 'account', 'data_schema': [ { 'name': 'user_title', @@ -243,6 +242,7 @@ def test_two_step_flow(hass, client): data = yield from resp.json() data.pop('flow_id') assert data == { + 'domain': 'test', 'type': 'create_entry', 'title': 'user-title', } @@ -262,7 +262,6 @@ def test_get_progress_index(hass, client): def async_step_account(self, user_input=None): return self.async_show_form( step_id='account', - title='Finish setup' ) with patch.dict(HANDLERS, {'test': TestFlow}): @@ -292,9 +291,7 @@ def test_get_progress_flow(hass, client): schema[vol.Required('password')] = str return self.async_show_form( - title='test-title', step_id='init', - description='test-description', data_schema=schema, errors={ 'username': 'Should be unique.' diff --git a/tests/components/test_hue.py b/tests/components/test_hue.py index fa61cb2b69e..78f8b573666 100644 --- a/tests/components/test_hue.py +++ b/tests/components/test_hue.py @@ -552,7 +552,7 @@ async def test_flow_link_timeout(hass): assert result['type'] == 'form' assert result['step_id'] == 'link' assert result['errors'] == { - 'base': 'Failed to register, please try again.' + 'base': 'register_failed' } @@ -568,7 +568,7 @@ async def test_flow_link_button_not_pressed(hass): assert result['type'] == 'form' assert result['step_id'] == 'link' assert result['errors'] == { - 'base': 'Failed to register, please try again.' + 'base': 'register_failed' } @@ -584,5 +584,5 @@ async def test_flow_link_unknown_host(hass): assert result['type'] == 'form' assert result['step_id'] == 'link' assert result['errors'] == { - 'base': 'Failed to register, please try again.' + 'base': 'register_failed' } diff --git a/tests/test_config_entries.py b/tests/test_config_entries.py index 3a1fe1d9d3e..5b1ec3b8ec0 100644 --- a/tests/test_config_entries.py +++ b/tests/test_config_entries.py @@ -226,14 +226,14 @@ def test_configure_reuses_handler_instance(manager): def async_step_init(self, user_input=None): self.handle_count += 1 return self.async_show_form( - title=str(self.handle_count), + errors={'base': str(self.handle_count)}, step_id='init') with patch.dict(config_entries.HANDLERS, {'test': TestFlow}): form = yield from manager.flow.async_init('test') - assert form['title'] == '1' + assert form['errors']['base'] == '1' form = yield from manager.flow.async_configure(form['flow_id']) - assert form['title'] == '2' + assert form['errors']['base'] == '2' assert len(manager.flow.async_progress()) == 1 assert len(manager.async_entries()) == 0 @@ -250,7 +250,6 @@ def test_configure_two_steps(manager): self.init_data = user_input return self.async_step_second() return self.async_show_form( - title='title', step_id='init', data_schema=vol.Schema([str]) ) @@ -263,7 +262,6 @@ def test_configure_two_steps(manager): data=self.init_data + user_input ) return self.async_show_form( - title='title', step_id='second', data_schema=vol.Schema([str]) ) @@ -299,9 +297,7 @@ def test_show_form(manager): @asyncio.coroutine def async_step_init(self, user_input=None): return self.async_show_form( - title='Hello form', step_id='init', - description='test-description', data_schema=schema, errors={ 'username': 'Should be unique.' @@ -311,8 +307,6 @@ def test_show_form(manager): with patch.dict(config_entries.HANDLERS, {'test': TestFlow}): form = yield from manager.flow.async_init('test') assert form['type'] == 'form' - assert form['title'] == 'Hello form' - assert form['description'] == 'test-description' assert form['data_schema'] is schema assert form['errors'] == { 'username': 'Should be unique.'