6

In Ubuntu 12.04 I have two input languages installed, English and Russian. I would like to disable use of Russian language in terminal - so that regardless of system-wide selection, terminal will always have english input language.

Is that possible?

The problem is, accidentally typed non-english characters may introduce a lot of pain (especially invisible ones).

UPDATE:

First of all, I'd like to thank all the participants - I am really excited how quickly people try to help!

Looks like I have to more clearly state the problem. The problem is that not only I'd like to have English switched on by default when I create new terminal window or switch to old terminal window, I'd also like to make impossible switching the language from English to Russian inside the terminal window.

Now, the results.

I've tried gxneur - looks like one has to build it from the sources, which I am not ready to try. I tried to install it with apt-get and could not figure out how to easily configure it. And it did not show the icon in the taskbar. So I removed it.

I've tried Python script and it immediately stops with following output:

No such schema 'org.gnome.desktop.input-sources'
Traceback (most recent call last):
  File "./set_language.py", line 63, in <module>
    lang_list = read_prev()
  File "./set_language.py", line 52, in read_prev
    currlang = get_lang()
  File "./set_language.py", line 24, in get_lang
    curr_n = int(get(key[1]+key[0]+key[4]).strip().split()[-1])
  File "./set_language.py", line 20, in get
    return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
  File "/usr/lib/python3.2/subprocess.py", line 522, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['/bin/bash', '-c', 'gsettings get org.gnome.desktop.input-sources current']' returned non-zero exit status 1

Finally, I've tried the shell script, it runs, but does not seem to work - I still can easily switch to Russian in terminal. And it also once in a while says

No such schema 'org.gnome.desktop.input-sources'

So, all in all, I could not make any of the solutions work.

I guess the bottom line here is that what I'd like to get is not that simple, so it's ok to not have it.

Jacob Vlijm
  • 83,767
oltish
  • 61

4 Answers4

4

Note on the answer below

The answer was originally written for 14.04, but rewritten January 6, 2017, to also work on (at least) 16.04 and 16.10. wmctrl is no longer needed.


Script to automatically set a different language for a single application.

enter image description here enter image description here

What it does

  • Running the script in the background, the user can set a different language for a specific application (in this case gnome-terminal). Just run the script and, with the application in front, set the desired language.
  • The language will be remembered, in the script (while running) as well as in a hidden file, to be remembered on the next time the script runs (on restart of the computer).
  • If the user sets focus to another application, the script switches back to the default language, whatever that was. Also the default language will be remembered, but user can change it any time (also the changed language is remembered)

Notes

  • The script uses an extended set of tools (functions) to take into account that user should be able to change the set of used languages, and the languages should be remembered, as suggested in the comment(s). Nevertheless it is very "light", since it only uses the function(s) when it is needed.

The script

#!/usr/bin/env python3
import subprocess
import time
import os
import ast

#--- set the "targeted" exceptional application below
app = "gnome-terminal"
#---

l_file = os.path.join(os.environ["HOME"], app+"_lang")
def_lang = os.path.join(os.environ["HOME"], "def_lang")
k = ["org.gnome.desktop.input-sources", "current", "sources"]

def get(cmd):
    # helper function
    try:
        return subprocess.check_output(cmd).decode("utf-8").strip()
    except subprocess.CalledProcessError:
        pass

def run(cmd):
    # helper function
    subprocess.Popen(cmd)

def front():
    # see if app has active window
    front = get(["xdotool", "getactivewindow"])
    data = get(["xprop", "-id", front])
    if all([front, data]):
        return app in get(["xprop", "-id", front])
    else:
        pass

def getlang():
    # get the currently set language (from index, in case the sources are changed)
    currindex = int(get(["gsettings", "get", k[0], k[1]]).split()[-1])
    return sources[currindex]

def get_stored(file):
    # read the set language
    return sources.index(ast.literal_eval(open(file).read().strip()))

def get_sources():
    return ast.literal_eval(get(["gsettings", "get", k[0], k[2]]))

sources = get_sources()
appfront1 = None
currlang1 = getlang()

while True:
    time.sleep(1)
    appfront2 = front()
    if appfront2 != None:
        currlang2 = getlang()
        # change of frontmost app (type)
        if appfront2 != appfront1:
            if appfront2:
                try:
                    run(["gsettings", "set", k[0], k[1], str(get_stored(l_file))])
                except FileNotFoundError:
                    open(l_file, "wt").write(str(currlang2))
            elif not appfront2:
                try:
                    run(["gsettings", "set", k[0], k[1], str(get_stored(def_lang))])
                except FileNotFoundError:
                    open(def_lang, "wt").write(str(currlang2))
        elif currlang2 != currlang1:
            f = l_file if appfront2 else def_lang
            open(f, "wt").write(str(currlang2))

        appfront1 = appfront2
        currlang1 = currlang2

How to use

  1. The script uses xdotool:

    sudo apt-get install xdotool
    
  2. Copy the script above into an empty file, save it as set_language.py

  3. Test-run it by the command:

    python3 /path/to/set_language.py
    

    While running the script:

    • set the (default) language.
    • open the (gnome-) terminal, set the language to be used with the terminal
    • Switch between the two and see if the language automatically switches.


    You can change both default language as the terminal language at any time. The set language(s) will be remembered.

  4. If all works as expected, add it to Startup Applications: Add to Startup Applications: Dash > Startup Applications > Add. Add the command:

    python3 /path/to/set_language.py
    

Explanation, the short (conceptual) story:

The script uses two files, to store the set languages for both the default language and the language, used in the exceptional application (gnome-terminal in this case, but you can set any application).

The script then periodically (once per second) does two tests:

  1. If the active window belongs to the exceptional application
  2. What is the currently set input language

The script compares the situation with the test(s) one second ago. Then if:

  1. there was a change in application:

    exceptional --> default: read language file for default language & set language. If the file does not exist (jet), create it, store the current language as default.
    default --> exceptional: the other way around.

  2. If there was a change in language (but not in window class):

    We may assume user set a different language for either the exceptional application or the default input language --> write the currently used input language into the according file (either for default language or the exceptional language).

Jacob Vlijm
  • 83,767
2

The Script

#!/bin/bash
# Author: Serg Kolo
# Date: June 16,2015
# Description: Script to ensure terminal 
# always uses english keyboard only

# set -x

PREVIOUS=$(wmctrl -lx | awk -v search=$(printf 0x0%x $(xdotool getactivewindow)) '{ if($1~search) print $3 }' )

while [ 1 ]; do

        # get WM_CLASS of currently active window
        WM_CLASS=$(wmctrl -lx | awk -v search=$(printf 0x0%x $(xdotool getactivewindow)) '{ if($1~search) print $3 }' )
        # echo "WM_CLASS"

        # check if that is gnome-terminal and if it wasn't
        if [ "$WM_CLASS" == "gnome-terminal.Gnome-terminal" ];then
        #  is current window is different class than preious ?
        # (i.e., did we switch from somewhere else)
        #  if yes, switch language
        #  if  we're still in gnome-terminal, do nothing
                if [ "$WM_CLASS" != "$PREVIOUS" ];then
                 # alternative command setxkbmap -layout us
                 gsettings set org.gnome.desktop.input-sources current 0
                fi

        fi

        PREVIOUS=$(echo "$WM_CLASS")
        sleep 0.250
done

Explanation in English

The script checks for the currently active window, and if the WM_CLASS matches that of gnome-terminal, it switches input language to the default one, or index 0. Save it as a text file, run sudo chmod +x scriptname.sh , and it is ready to perform.

This script requires installation of wmctrl program, which is key to the script's functionality. To install it, run sudo apt-get install wmctrl.

To make it run continuously on every login, add the full path to the script to Startup Applications or create custom .desktop file in /home/yourusername/.config/autostart . A variation on the theme of using .desktop files is Takkat's answer.

This script can be adapted in a number of ways. Knowing WM_CLASS of your desired program (from output wmctrl -lx ), you can substitute gnome-terminal.Gnome-terminal for any other program class in the if [ "$WM_CLASS" == "string" ];then line. You can also set which language to force, by knowing the indexes of your languages (just count them top to botom in the drop down menu, starting at 0 with the top one) and altering gsettings set org.gnome.desktop.input-sources current 0. Among other things, if you add multiple else if statements, there's possibility to force different languages in different programs. The script is simple and very flexible.

Explanation in Russian

Скрипт выше следит за окнами которые активны , и если окно относится к классу gnome-terminal.Gnome-terminal , язык моментально меняется на английский.

Для того что бы этот скрипт работал требуется установка программы wmctrl - это самая важная часть, которую можно установить с командой sudo apt-get isntall wmctrl.

Для того что бы этот скрипт работал автоматически, сохраните в каком-то файле (на пример с именем myscript.sh), поменяйте разрешения этого файла с командой sudo chmod +x /full/path/to/myscript.sh (где /full/path/to/myscript.sh это полный аддресс где находится файл), и добавьте полный аддресс к этому скрипту как одна из Startup Applications. Или же можно создать .desktop файл.

Этот скрипт можно адаптировать под другие программы. Просто узнайте какой класс у той программы при промощи команды wmctrl -lx - это третий столбик в результате. Если есть желание, можно добавить другие программы с прибавлением конструкции else if

Sources:

https://askubuntu.com/a/414041/295286

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
1

The only way I know is to use gxneur.

It is buggy in Ubuntu for automatic switching layout, but is good for these kind of settings. Automatic switching can be easily disabled.

You can set there applications, like gnome-terminal, to have single layout.

You can read THIS TOPIC in Russian by gxneur maintainer.

But I also will be happy if there is a better way.

Pilot6
  • 90,100
  • 91
  • 213
  • 324
1

All of a sudden I found a very simple solution, that does not need any scripting.

You can click language indicator, select "Text Entry Settings...".

In the opened window check "Allow different sources for each window" and

"New window use the default source".

enter image description here

If default layout is English, each newly opened application will be started with English layout, including terminal.

Pilot6
  • 90,100
  • 91
  • 213
  • 324
  • I just realize.. The default language of OP will probably be Russian. – Jacob Vlijm Jun 17 '15 at 18:08
  • I always have default language English since long time ago on Windows. For this reason, not to type accidentally anything wrong. xneur is good that if you entered in a wrong layout it will rewrite it in a correct one on one button press. But some people have Russian default. I type much much more in English than in Russian. So there are a lot of choices now )) – Pilot6 Jun 17 '15 at 18:11
  • 1
    @JacobVlijm Perfect solution will be to make an option: "New windows use the selected source..." and allow user to select. Gxneur has that even for specific apps. – Pilot6 Jun 17 '15 at 18:16
  • 1
    That is the perfect set up, going to make a GUI for it! – Jacob Vlijm Jun 17 '15 at 18:17
  • @JacobVlijm You can look at gxneur code. I guess GUI is in python too. There is a list of apps that can have fixed layout on open. – Pilot6 Jun 17 '15 at 18:19
  • I will, I found it :) – Jacob Vlijm Jun 17 '15 at 18:22
  • well the problem is in already existing windows unfortunately, but thanks, this one is neat – oltish Jun 23 '15 at 17:30