adhearsion/adhearsion-i18n

How to handle interpolations?

bklang opened this issue · 12 comments

I18n#t allows interpolating strings like:

en:
  foo: Hello %{name}
t(:foo, name: "Ben") # => "Hello Ben"

This would be fine for TTS prompts but would be relatively difficult to manage for audio prompts. How should be handle this?

Follow the simple case for basic strings, and defer more complex cases to SSML templating.

@CodeMangler brought up a use-case I had not thought of: using the string interpolation within audio files for constructing their source URL. I think this supports what @benlangfeld said. I will document this in the README:

  • Interpolation is available with I18n
  • However, Best Practices dictate that you should not use interpolation for variables that contain strings to be read to the user if you are using audio prompts. Instead, use SSML for that, or something like:
play t(:hello, server: "server1"), name

And your YAML like this:

en:
  hello:
    text: "Hello"
    audio: "http://%{server}/hello.wav"

This form allows mixed TTS + recorded audio.

@bklang The variables we had to interpolate were ENV variables. Specifically, S3 bucket for the audio files. We had to support audio file URLs like: "https://%{s3_bucket}.s3.amazonaws.com/file.mp3" in our I18n yml files, where s3_bucket is configured in ENV. For this, we use a custom wrapper over I18n that passes the necessary ENV parameters to I18n.t transparently.

Can adhearsion-i18n support this? What's the recommended way to handle this?

/cc @benlangfeld

@CodeMangler If you look at the example in my previous comment, it should be pretty straightforward. It would look something like this:

play t(:hello, bucket: ENV['EC2_BUCKET_NAME']), name

And your YAML like this:

en:
  hello:
    text: "Hello"
    audio: "http://%{bucket}.s3.amazonaws.com/hello.wav"

@bklang true. But that got noisy pretty quickly. Every call to I18n.t needed these variables explicitly passed in, which we didn't like. We ended up having a wrapper around I18n that did this for us.

Though ours was a custom solution, built to solve a specific case, I was hoping for a generic feature similar to it (i.e. transparently passing in a selected list of variables to t).

All you need to do is define a base call controller for your application and have all your call controllers inherit from it:

class ApplicationCallController < Adhearsion::CallController
  def t(key, options)
    options.merge! bucket: ENV['EC2_BUCKET_NAME']
    super
  end
end

class MyController < ApplicationCallController
  def run
    play t(:hello)
  end
end

If you don't like inheritance, this could also be done as a mixin.

Updated previous example to fix typo (MyController inherits from ApplicationCallController)

@bklang yep. We have something similar.

So is there still an issue? Or is this solved?

Our solution works (it's similar to defining a method in the base controller), so, it's not really a pressing issue.

The reason I brought this up was because I felt having this feature in the framework, instead of the application code is better. But I don't really have a reason why adhearsion-i18n should support this. I'm not sure if anyone else would have similar requirements, so, you can consider this solved.

Thanks for your input on this.

I'd prefer to have the adhearsion-i18n implementation not stray too far from the upstream i18n implementation. If it's important to you, perhaps you could raise it as an feature request (support default interpolations) on the i18n library?

I've added notes from our conversation to the README as well. Thanks!