# Language Handler Problems

**URL:** <https://forums.sketchup.com/t/language-handler-problems/54974>\
**Category:** Ruby API\
**Created:** [November 12, 2017, 7:04pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974 "2017-11-12T19:04:38Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![medeek](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/medeek/32/10675_2.png) [@medeek](https://forums.sketchup.com/u/medeek)\
**Post date:** [November 12, 2017, 7:04pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/1 "2017-11-12T19:04:38Z")

</div>

I’m trying to get the language handler to work but for the life of me I can’t get it to translate.

My code that loads it up is here:

```ruby

# First we pull in the standard API hooks.

require 'sketchup.rb'
require 'extensions.rb'
# require 'langhandler.rb'

# Define Module Hierarchy

module Medeek_Engineering_Inc_Extensions

	module MedeekTrussPlugin
	
	# require 'langhandler.rb'
	# LH = LanguageHandler.new("medeek_truss.strings")

##############################
#
# Class Methods of Plugin
#
##############################

class MedeekMethods
  	class << self

include Math

require 'langhandler.rb'
LH = LanguageHandler.new("medeek_truss.strings")

```

Then I call it up in my first prompt:

```ruby
prompts1 = [LH["Truss Type: "], "Out-to-out Span (ft.): ", "Top chord Pitch (x/12): ", "Overhang Left (in.): ", "Overhang Right (in.): ", "TC Size (in.): ", "BC Size (in.): ", "Web Size (in.): ", "Ply Thickness (in.): ", "Raised Heel: ", "Heel Height (in.): "]
 			defaults1 = ["#{@Trusstype}", "#{@TrussSpan_ft.round(5)}", "#{@Pitch}", "#{@Overhangl}", "#{@Overhangr}", "#{@Tcd}", "#{@Bcd}", "#{@Webd}", "#{@Ply}", "#{@Raisedheel}", "#{@Usrhh}"]
 			list1 = ["King Post|Queen Post|Fink|Howe|Fan|Mod Queen|Double Fink|Double Howe|Mod Fan|Triple Fink|Triple Howe|Quad Fink", "", "2.5|3.0|3.5|4.0|4.5|5.0|5.5|6.0|6.5|7.0|7.5|8.0|8.5|9.0|9.5|10.0|10.5|11.0|11.5|12.0|12.5|13.0|13.5|14.0|14.5|15.0|15.5|16.0", "", "", "3.5|5.5|7.25|9.25|9.5|11.25|11.875|14.0|16.0", "3.5|5.5|7.25|9.25|9.5|11.25|11.875|14.0|16.0", "3.5|5.5|7.25|9.25|11.25", "", "NO|YES", ""]
 		

```

In my medeek\_truss.strings file I have this line:

`"Truss Type: "="Type de Treillis: ";`

I’ve put this file into the Resources/en-US subfolder.

All that displays is the original phrase "Truss Type: ".

What am I missing? I’ve mucked around with this for over an hour now and nothing.

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [November 12, 2017, 7:15pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/2 "2017-11-12T19:15:11Z")

</div>

> [@medeek](#):
>
> I’ve put this file into the Resources/en-US subfolder.

your own or SU’s…

```ruby
LH = LanguageHandler.new("medeek_truss.strings")

```

SU will be looking for

```ruby
 "YourExtensionFolder/Resources/en-US/medeek_truss.strings"

```

is that where it is?

john

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [November 12, 2017, 7:21pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/3 "2017-11-12T19:21:27Z")

</div>

for prompts it’s easiest to convert an array…

```ruby
      prompts = [
        'Radius of Circle',
        'Circle Segments',
        'Wave Count',
        'Wave Height',
        'Create Single Wave',
        'with Circle',
        'with Surface',
        'with Cylinder',
        'with Castellation',
        'Face Thickness',
        'Explode Grouping'
        ]

      @prompts = prompts.each do |prompt|
       TRANSL8[prompt]
      end
``
```

---

<div class="post-metadata">

**Author:** ![john\_mcclenahan](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/john_mcclenahan/32/135377_2.png) [@john\_mcclenahan](https://forums.sketchup.com/u/john_mcclenahan)\
**Post date:** [November 13, 2017, 1:04am UTC](https://forums.sketchup.com/t/language-handler-problems/54974/4 "2017-11-13T01:04:57Z")

</div>

> [@medeek](#):
>
> I’ve put this file into the Resources/en-US subfolder.

From what I remember of the work Steve (@slbaumgartner) did helping me to redevelop his original Angular Dimension plugin, you need to put it into a folder for the language you are going to use - looks like French in this example.

Have a look at the Angular Dimension 2 plugin from Sketchucation to see how the language handler is used there.

Steve set up the code to use langhandler, and I did most of the work using Google Translate and a little feedback from users to create the data files for it, and to test them.

Here’s the file structure under Resources in the Angular Dimensions 2 plugin folder:  
 ![image](https://global.discourse-cdn.com/sketchup/original/3X/b/f/bf40228354f522c5cd367b96f4b447634383880d.png)

You need to put the _.strings_ files into a separate subfolder for each language, I think, using the appropriate language code (two letters, except for en-US and pt\_BR in our case).

We used a separate method to set up the HTML web-dialogue pages, using placeholder tokens where different languages need different words in the page. I wrote some code that took the original tokenised page, substituted the translation for the token, and generated the language specific web-dialogue HTML pages. They, and the translation strings used to create them, are also preserved in the individual language folders in Resources, but for that we used pipe separated strings, not quoted strings with = signs.

This isn’t the only way to do it, but it worked for us. Internally, if I recall correctly what Steve said, the language handler gets a language code back from the local regional settings (I don’t think it’s the SU installation), and uses it to decide which _.strings_ file to use.

That makes it quite tricky to test, as it isn’t that easy to set up different language versions of your OS, whether Mac or Windows, but Steve wrote code to allow the plugin language to be changed by the user, regardless of OS or SU’s own settings.

PS.

If I as I assume you are using an en-US version of SU, I’m not quite sure what happens when you put a translation file in the en-US folder. IIRC if language handler doesn’t find a translation for a particular term in a particular language, it falls back to using the native ‘hard coded’ US terminology, so we don’t have any _.strings_ file in the en-US Resources subfolder, just the conversions from tokens to English for the HTML pages.

Try putting the file in a _fr_ sub folder and pointing Language Handler to that.

---

<div class="post-metadata">

**Author:** ![medeek](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/medeek/32/10675_2.png) [@medeek](https://forums.sketchup.com/u/medeek)\
**Post date:** [November 13, 2017, 2:40am UTC](https://forums.sketchup.com/t/language-handler-problems/54974/5 "2017-11-13T02:40:05Z")

</div>

I have it precisely like this.

---

<div class="post-metadata">

**Author:** ![medeek](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/medeek/32/10675_2.png) [@medeek](https://forums.sketchup.com/u/medeek)\
**Post date:** [November 13, 2017, 2:41am UTC](https://forums.sketchup.com/t/language-handler-problems/54974/6 "2017-11-13T02:41:24Z")

</div>

To test it I put the medeek\_truss.strings file (french version) into the en-US folder but it won’t load the values.

---

<div class="post-metadata">

**Author:** ![medeek](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/medeek/32/10675_2.png) [@medeek](https://forums.sketchup.com/u/medeek)\
**Post date:** [November 13, 2017, 3:29am UTC](https://forums.sketchup.com/t/language-handler-problems/54974/7 "2017-11-13T03:29:19Z")

</div>

I tried installing the French version of SketchUp on my same computer that I already have the english version installed, that does not seem to work, only the english version will load.

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [November 13, 2017, 3:29am UTC](https://forums.sketchup.com/t/language-handler-problems/54974/8 "2017-11-13T03:29:30Z")

</div>

> [@medeek](#):
>
> (french version) into the en-US folder

it should after a restart…

any line with any error will fail silently to english…

john

---

<div class="post-metadata">

**Author:** ![medeek](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/medeek/32/10675_2.png) [@medeek](https://forums.sketchup.com/u/medeek)\
**Post date:** [November 13, 2017, 6:26am UTC](https://forums.sketchup.com/t/language-handler-problems/54974/9 "2017-11-13T06:26:54Z")

</div>

I’ve implemented the array technique, that will eventually save me a lot of time:

```ruby

if @Roofslope_db == "PITCH"
			prompts1 = ['Truss Type', "Out-to-out Span (ft.): ", "Top chord Pitch (x/12): ", "Overhang Left (in.): ", "Overhang Right (in.): ", "TC Size (in.): ", "BC Size (in.): ", "Web Size (in.): ", "Ply Thickness (in.): ", "Raised Heel: ", "Heel Height (in.): "]
 			defaults1 = ["#{@Trusstype}", "#{@TrussSpan_ft.round(5)}", "#{@Pitch}", "#{@Overhangl}", "#{@Overhangr}", "#{@Tcd}", "#{@Bcd}", "#{@Webd}", "#{@Ply}", "#{@Raisedheel}", "#{@Usrhh}"]
 			list1 = ["King Post|Queen Post|Fink|Howe|Fan|Mod Queen|Double Fink|Double Howe|Mod Fan|Triple Fink|Triple Howe|Quad Fink", "", "2.5|3.0|3.5|4.0|4.5|5.0|5.5|6.0|6.5|7.0|7.5|8.0|8.5|9.0|9.5|10.0|10.5|11.0|11.5|12.0|12.5|13.0|13.5|14.0|14.5|15.0|15.5|16.0", "", "", "3.5|5.5|7.25|9.25|9.5|11.25|11.875|14.0|16.0", "3.5|5.5|7.25|9.25|9.5|11.25|11.875|14.0|16.0", "3.5|5.5|7.25|9.25|11.25", "", "NO|YES", ""]
 		elsif @Roofslope_db == "ANGLE"
			prompts1 = ['Truss Type', "Out-to-out Span (ft.): ", "Top chord Angle (deg): ", "Overhang Left (in.): ", "Overhang Right (in.): ", "TC Size (in.): ", "BC Size (in.): ", "Web Size (in.): ", "Ply Thickness (in.): ", "Raised Heel: ", "Heel Height (in.): "]
 			defaults1 = ["#{@Trusstype}", "#{@TrussSpan_ft.round(5)}", "#{@Pitch_deg}", "#{@Overhangl}", "#{@Overhangr}", "#{@Tcd}", "#{@Bcd}", "#{@Webd}", "#{@Ply}", "#{@Raisedheel}", "#{@Usrhh}"]
 			list1 = ["King Post|Queen Post|Fink|Howe|Fan|Mod Queen|Double Fink|Double Howe|Mod Fan|Triple Fink|Triple Howe|Quad Fink", "", "", "", "", "3.5|5.5|7.25|9.25|9.5|11.25|11.875|14.0|16.0", "3.5|5.5|7.25|9.25|9.5|11.25|11.875|14.0|16.0", "3.5|5.5|7.25|9.25|11.25", "", "NO|YES", ""]
 		
		else
			UI.messagebox("Non-valid roof slope type, action aborted.") 
			exit 0
		end

		@prompts1 = prompts1.each do |prompt|
			LH[prompt]
			puts LH[prompt]
		end
	
		@Inputs1 = UI.inputbox(@prompts1, defaults1, list1, "Medeek Truss Plugin - Geometry")

```

Still can’t get it to work though. Must be the way I have all these multiple nested modules and classes that is messing things up.

This language handler does not seem very robust, I might just have to build my own like Garry K. has done.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [November 13, 2017, 8:12am UTC](https://forums.sketchup.com/t/language-handler-problems/54974/10 "2017-11-13T08:12:28Z")

</div>

> [@medeek](#):
>
> I tried installing the French version of SketchUp on my same computer that I already have the english version installed, that does not seem to work, only the english version will load.

No you cannot have two editions of the same year release on the same computer. (Both will be overwriting each others registry entries also, possibly causing havoc.)

_In related thread_: [Creating language resource files](https://forums.sketchup.com/t/creating-language-resource-files/6354/)

> [@Creating language resource files](https://forums.sketchup.com/t/creating-language-resource-files/6354/7):
>
> Fun fact: With a start-up parameter **`-lang=fr`** the locale can be overriden with whatever string you like – even **`pfl`** – and it would then look for a **`pfl`** folder.

So you can create a series of desktop icons for testing in the various supported languages, by editing the “Target:” field, of the “Shortcut” tab, of the icon’s “Properties”.

I think you would just add a space and then `"-lang=fr"` after the pathname to a copy of the standard icon made by the installer. Then of course you’d change the shortcut’s name to indicate French.

Repeat for other languages.

Only run one language test application instance at a time (as they’ll be sharing the same registry hive.)

Note what Thomas says concerning [**_`Sketchup::get_locale()`_**](http://ruby.sketchup.com/Sketchup.html#get_locale-class_method):

> [@Language handler question](https://forums.sketchup.com/t/language-handler-question/7205/9):
>
> Will always return the locale of the language version of SketchUp you installed. If you want to test your strings you can follow these instructions: [Localized Strings · Issue #45 · SketchUp/sketchup-stl · GitHub](https://github.com/SketchUp/sketchup-stl/issues/45#issuecomment-10819945) (We need to document that better.)

* * *

## FYI:

Swedish has been added recently. NL was dropped after v8. Russian may have been dropped for a few years after v8.

#### Related posts elsewhere:

- [Tyle Miller on the `/lang` command line parameter (GitHub: SketchUp STL extension project issues)](https://github.com/SketchUp/sketchup-stl/issues/45#issuecomment-10819945)

#### Related topic threads:

- [Creating language resource files](https://forums.sketchup.com/t/creating-language-resource-files/6354/)

- [Language handler question](https://forums.sketchup.com/t/language-handler-question/7205) ( **_`GetString`_** vs **_`[]`_** method calls)

- [Case sensitivity and LanguageHandler](https://forums.sketchup.com/t/case-sensitivity-and-languagehandler/24574)

- [Using format string parameter replacement with LanguageHandler](https://forums.sketchup.com/t/using-format-string-parameter-replacement-with-languagehandler/24766)

… and from those, other nuggets you should know:

> [@Language handler question](https://forums.sketchup.com/t/language-handler-question/7205/20):
>
> The strings files need to be encoded as UTF-8 without Bit Order Mark. (Just plain UTF-8 in Notepad++, NOT the UTF-8-BOM choice.) Your Ruby files should also be encoded the same, and have a “magic comment” as the first line, like this: # encoding: UTF-8

> [@Case sensitivity and LanguageHandler](https://forums.sketchup.com/t/case-sensitivity-and-languagehandler/24574/4):
>
> Let me try to get the most important theme across to you about the LanguageHandler class. The LanguageHandler class is: dumb, ie, it has no “smarts” nor “intelligence” it is a simple “lookup” function it look’s up a key being an English string in a Ruby [Hash](http://ruby-doc.org/core-2.0.0/Hash.html), and returns the string value for that key. the string value is the local language that YOU manually translated when you created all the various .strings files for your extension. the LanguageHandler class does NOT translate English “…

> [@Case sensitivity and LanguageHandler](https://forums.sketchup.com/t/case-sensitivity-and-languagehandler/24574/8):
>
> It has two copies of every string in it’s internal hash. But you can eliminate this, by only temporarily creating a LanguageHandler object, extracting the locale string translations to some internal references, and then disposing of the LanguageHandler object. For example, during startup, build up the arrays of your inputbox prompts, defaults, options, etc., and assign references to some persistent object (local constants, or module variables, etc.) require 'langhandler.rb' @lang = LanguageH…

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [November 13, 2017, 9:43am UTC](https://forums.sketchup.com/t/language-handler-problems/54974/11 "2017-11-13T09:43:31Z")

</div>

> [@medeek](#):
>
> This language handler does not seem very robust, I might just have to build my own like Garry K. has done.

As I mentioned in some of the other threads …

> [@Case sensitivity and LanguageHandler](https://forums.sketchup.com/t/case-sensitivity-and-languagehandler/24574/4):
>
> the **`LanguageHandler`** class uses twice the amount of memory just loading your translated strings into a Ruby hash does.

…

> [@Case sensitivity and LanguageHandler](https://forums.sketchup.com/t/case-sensitivity-and-languagehandler/24574/8):
>
> I think the Ruby’s compiled parser is faster at parsing a ruby script with just a hash definition, then **`LanguageHandler`** ’s Ruby parser parsing “strings” files.
> 
> I find **`LanguageHandler`** ’s implementation awkward and clunky.

Keep in mind the interpreter parser is compiled C while the LanguageHandler class’ parser is interpreted Ruby.  
…

> [@Case sensitivity and LanguageHandler](https://forums.sketchup.com/t/case-sensitivity-and-languagehandler/24574/4):
>
> For these reasons, I do not use the **`LanguageHandler`** class at all. I just write Ruby files (that are part of the extension’s files,) that define a language hash (within my extension module) that uses short symbol keys.

I’m not sure if I have posted an example, but basically I just create a “ **`lang`** ” subfolder of my plugin folder, and populate it with **`.rb`** scripts that use a naming syntax like “`#{LANG}.rb`”, where the plugin constant **`LANG`** is either a specific language the user has selected in my plugin’s options dialog (which can be even languages the SketchUp doesn’t even ship using,) or (upon first run) the string returned by **`Sketchup::get_locale()`**.

In the main plugin file, I’d define some lang constants used by all languages:

```ruby
# encoding: UTF-8
module Author::SomePlugin

  KEY ||= Module.nesting.name[0].gsub('::','_') # qualified registry / plist key

  LANGCODES ||= Hash[
    :english,'en-US', :french,'fr', :italian,'it',
    :german,'de', :spanish,'es', :japan,'ja',
    :korean,'ko', :china,'zh-CN', :taiwan,'zh-TW',
    :portbraz,'pt-BR', :dutch,'nl', :russian,'ru'
  ]

  LANG ||= Sketchup.read_default(KEY,'lang') 
  if LANG.nil? # has not been set (1st run)
    LANG = Sketchup::get_locale # set it
    Sketchup.write_default(KEY,'lang',LANG) # store it
  end
  LANGFILE ||= File.join( File.dirname( __FILE__ ),"lang/#{LANG}.rb" )
  load(LANGFILE) rescue load( File.join( File.dirname( __FILE__ ),'lang/en-US.rb' ))

end

```

Then the contents of the language ruby scripts for **`"lang/en-US.rb"`** would be like:

```ruby
# encoding: UTF-8
module Author::SomePlugin

  OPTIONS_PROMPTS ||= {
    :lang => 'Language',
    :data => 'Data Path',
    :save => 'Save Path:',
    # etc., etc., ...
  }

  OPTIONS_ITEMS ||= {
    :lang => LANGCODES.join('|'),
  }

  STATUSBAR ||= {
    :tool1 => 'This tool does such and so forth',
    :tool2 => 'This tool does more than any other'
    # etc., etc., ...
  }

  # ETC., ETC., ...

end

```

Then I copy the english RB file a number of times and edit it and rename it for other languages.

---

<div class="post-metadata">

**Author:** ![eneroth3](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/eneroth3/32/1222_2.png) [@eneroth3](https://forums.sketchup.com/u/eneroth3)\
**Post date:** [November 13, 2017, 11:57am UTC](https://forums.sketchup.com/t/language-handler-problems/54974/12 "2017-11-13T11:57:43Z")

</div>

I really like how this approach uses identifiers different from the English string. A lot of the faulty translations in SketchUp is because things are translated out of context. E.g. Extension could both be a Ruby extension or the style setting of extending visually extending edges (View \> Edges \> Extension). Group could both be a verb and a noun (though newer SU versions call the action “Make Group in the context menu”).

Using identifiers such as tool\_status\_pick\_entity, tool\_status\_modify, ro\_extend\_edges etc is safer, especially when the translators are sloppy.

---

<div class="post-metadata">

**Author:** ![medeek](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/medeek/32/10675_2.png) [@medeek](https://forums.sketchup.com/u/medeek)\
**Post date:** [November 13, 2017, 4:19pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/13 "2017-11-13T16:19:46Z")

</div>

I like what I see here but I’m trying to figure out if I can implement the system you’ve described above and still somehow use the array technique given by John so that I don’t need to completely rewrite all of my prompts. Unfortunately, I have a lot of them so any time saver is huge.

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [November 13, 2017, 4:38pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/14 "2017-11-13T16:38:37Z")

</div>

> [@medeek](#):
>
> I might just have to build my own

I and many other people have rolled our own in the past…

it’s the main reason a generic translation tool has never been successfully developed…

The ‘biggest’ problem with `LanguageHandler` was addressed in SU v14…

The ‘small’ change was the ability to have our own ‘Resources’ folder structure, removing the need to store files in SU’s application folder…

`LanguageHandler` has a few ‘gotcha’s’, but they can be circumvented…

one is it uses a existing file format that doesn’t play well with ruby…

> Associated file extensions: .strings  
> i18n type: STRINGS  
> Encoding: UTF-16  
> .strings files are used for localizing macOS and iOS apps.

I’m not sure if/how this effects windows…

it is an issue on mac [at least], but as `LanguageHandler` discounts any line containing `/ or */` you can add an encoding to the file and save to match…

`# encoding: UTF-8 // langhandlers completely skips any line with // or */ `  
another is it documentation implies the need for ‘one to one’ en-US strings, which makes updating in code text difficult…

Apples example uses keywords and comments to aid translation…

> /\* registration information: Username\*/  
> “username” = “Username:”;  
> /\* registration information: Password\*/  
> “password” = “Password:”;  
> /\* registration information: Email Address\*/  
> “email\_address” = “Email Address:”;  
> /\* registration information: User Role\*/  
> “user\_role” = “User Role”;  
> /\* registration information: Phone\*/  
> “phone” = “Phone”;  
> /\* registration information: Country\*/  
> “country” = “Country”;

> [@medeek](#):
>
> the array technique given by John

I should probably pushed the prompts in a ruby fashion…

```ruby
      @prompts = []
      prompts.each do |prompt|
        @prompts << TRANSL8[prompt]
      end

```

may be why your test didn’t work…

john

---

<div class="post-metadata">

**Author:** ![eneroth3](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/eneroth3/32/1222_2.png) [@eneroth3](https://forums.sketchup.com/u/eneroth3)\
**Post date:** [November 13, 2017, 5:19pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/15 "2017-11-13T17:19:15Z")

</div>

> [@john\_drivenupthewall](#):
>
> ```
> @prompts = []
> prompts.each do |prompt|
> @prompts &lt;&lt; TRANSL8[prompt]
> end
> 
> ```

Or

```
@promts = prompts.map { |p| TRANSL8[p] }

```

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [November 13, 2017, 6:27pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/16 "2017-11-13T18:27:00Z")

</div>

I have a personal dislike for using `|p| ` but `:map` is possibly a better approach…

EDIT: rubocop tells me this is ‘best’ for the strings…

```ruby
    prompts = %w(
      radius
      segments
      frequency
      height
      line_only
      with_circle
      with_surface
      with_cylinder
      with_castellation
      surface_thickness
      explode_groups
    )

     @prompts = prompts.map { |prompt| TRANSL8[prompt] }

```

and then in the strings remembering the other 'LanguageHandler ‘gotcha’…

`keyvalue = entryString.split('"="')`

hardcoded to NOT accept whitespace around the `=`…

```ruby
# encoding: UTF-8 // langhandlers completely skips any line with // or */
"The string file can be translated"="The string file can be translated";
"Sine Circle Details"="Sine Circle Details";
"radius"="Radius of Circle";
"segments"="Circle Segments";
"frequency"="Wave Count";
"height"="Wave Height";
"line_only"="Create Single Wave";
"with_surface"="with Surface";
"with_circle"="with Circle";
"with_cylinder"="with Cylinder";
"with_castellation"="with Castellation";
"surface_thickness"="Face Thickness";
"explode_groups"="Explode Grouping";
"parram_legend"="Set parrameters for Wave";

```

one advantage this has is you can see if the en-US file works, before trying other languages…

 ![sine_circle](https://global.discourse-cdn.com/sketchup/original/3X/b/c/bc12b49b01173f5a018d133bb93746fef02036f9.png)

john

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [November 13, 2017, 7:08pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/17 "2017-11-13T19:08:15Z")

</div>

I would really like to encourage everyone to using `Langhandler` to make translation of any extensions easier for the User base…

I started this in 2013 and it has been used by many developers and users since then…

but it only works on SU’s version of .string files…

 ![transl8](https://global.discourse-cdn.com/sketchup/original/3X/8/9/89471918edf6104719d71bd0b094d27b0c5a065d.gif)

if you don’t ‘understand’ a language, using phrases or word combinations gets better matches…

when a native speaker uses this and sends you the file, it’s even better…

it is also not limited to the ‘SU’ supported languages…

john

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [November 14, 2017, 4:43pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/18 "2017-11-14T16:43:58Z")

</div>

> [@john\_drivenupthewall](#):
>
> I would really like to encourage everyone to using Langhandler to make translation of any extensions easier for the User base… I started this [translation utility] in 2013 and it has been used by many developers and users since then… **but it only works on SU’s version of `.strings` files** …

Yes that is nifty, but it can be used to translate strings, and then later still use hash or another author specific format, by using a Ruby utility to read **`.strings`** files and convert to something else.

There are two separate issues here. The translation of strings, and the workings of **`LanguageHandler`** class objects.

* * *

The latter is what is “ **clunky** ”. All example code shows creating and using perpetual **`LanguageHandler`** instance objects, which waste memory (2 copies of every string,) and are extremely slow (ie, Ruby String comparison.)

The examples encourage coders to look up the translated string in the **`LanguageHandler`** instance object each time it is needed. This is what I mainly take issue with.

Instead an extension (if it uses **`LanguageHandler`** instance objects,) … should do _most_ it’s lookups when it first loads up, and store the translated strings in extension local objects (arrays, hashes, openstructs or sets, etc.) Then dispose of the **`LanguageHandler`** instance object(s).

One of my longest “pet peeves” are the perpetual global **`LanguageHandler`** instance objects created by all of the Trimble extensions. They sit there in memory even when the extensions are not being used !

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [November 14, 2017, 4:54pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/19 "2017-11-14T16:54:19Z")

</div>

this is the trace from loading Sine Circle…

```auto
"start"
[54, LanguageHandler, :[], "Sine Circle Details"]
[54, LanguageHandler, :[], "Click to Close"]
"HtmlDialog"
[54, LanguageHandler, :[], "Radius of Circle"]
[54, LanguageHandler, :[], "Circle Segments"]
[54, LanguageHandler, :[], "Wave Count"]
[54, LanguageHandler, :[], "Wave Height"]
[54, LanguageHandler, :[], "Create Single Wave"]
[54, LanguageHandler, :[], "with Circle"]
[54, LanguageHandler, :[], "with Surface"]
[54, LanguageHandler, :[], "with Cylinder"]
[54, LanguageHandler, :[], "with Castellation"]
[54, LanguageHandler, :[], "Face Thickness"]
[54, LanguageHandler, :[], "Explode Grouping"]
[54, LanguageHandler, :[], "Help"]
[50, Length, :initialize, 196.8503937007874]
[54, LanguageHandler, :[], "Set parrameters for Wave"]
[31, Length, :to_f, 196.8503937007874]
[54, LanguageHandler, :[], "Cancel"]
[54, LanguageHandler, :[], "OK"]

```

it appears to use the key, once…

john

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [November 14, 2017, 5:14pm UTC](https://forums.sketchup.com/t/language-handler-problems/54974/20 "2017-11-14T17:14:01Z")

</div>

> [@medeek](#):
>
> I like what I see here but I’m trying to figure out if I can implement the system you’ve described above and still somehow use the array technique given by John **so that I don’t need to completely rewrite all of my prompts**.

If you refer to how you coded in this post …

> [@Language Handler Problems](https://forums.sketchup.com/t/language-handler-problems/54974/9):
>
> I’ve implemented the array technique, that will eventually save me a lot of time: if @Roofslope\_db == "PITCH" prompts1 = ['Truss Type', "Out-to-out Span (ft.): ", "Top chord Pitch (x/12): ", "Overhang Left (in.): ", "Overhang Right (in.): ", "TC Size (in.): ", "BC Size (in.): ", "Web Size (in.): ", "Ply Thickness (in.): ", "Raised Heel: ", "Heel Height (in.): "] defaults1 = ["#{@Trusstype}", "#{@TrussSpan\_ft.round(5)}", "#{@Pitch}", "#{@Overhangl}", "#{@Overhangr}", "#{@Tcd}", "#{@Bcd}"…

… then I’m sorry, but that is “hard-wired” to use a single language (and a single unit of measure, _which is a separate issue_.)

* * *

You need to think about multilanguage support at the beginning, and code in a more flexible way.

**Since you did not** , then you’ll definitely need to do some code refactoring, but it will be educational, and perhaps a bit “painful”, but that’ll just provide more encouragement to do things better from the start, next time.

Build your prompt, default and choice arrays at the loadup of your extension (or sub-modules), and store them referenced by local constants, ie, **`PITCH_PROMPTS`** , **`PITCH_DEFAULTS`** , **`PITCH_CHOICES`** , **`ANGLE_PROMPTS`** , etc.

```ruby
if @Roofslope_db == "PITCH"
  @Inputs1 = UI.inputbox( PITCH_PROMPTS, PITCH_DEFAULTS, PITCH_CHOICES, CAPTION )
elsif @Roofslope_db == "ANGLE"
  @Inputs1 = UI.inputbox( ANGLE_PROMPTS, ANGLE_DEFAULTS, ANGLE_CHOICES, CAPTION )
else
  UI.messagebox( ERROR_TEXT["Non-valid roof slope type, action aborted."] )
  raise InvaildRoofTypeError # <-- local RuntimeError subclass
end

```

This makes code much more readable and hence easier to maintain.

(Notice that I replaced **`"exit 0"`** with a raising of a plugin specific runtime exception. **`SystemExit`** has no real use in an embedded Ruby interpreter, and used to cause a BugSplat in older SketchUp versions.)

[Next page](https://forums.sketchup.com/t/language-handler-problems/54974.md?page=2)
