Tetapkan bahasa keyboard default per-aplikasi

11

Apakah mungkin untuk menetapkan bahasa keyboard default untuk aplikasi tertentu? Saya tahu bahwa ada opsi untuk selalu memulai aplikasi dengan bahasa keyboard standar tetapi ini bukan yang saya inginkan.

Saya mencari sesuatu yang mirip dengan "ruang kerja tetap" yang dapat Anda atur menggunakan CompizConfig (Anda mengatur Chrome untuk selalu terbuka di X1Y1, terminal di X2Y1 dll). Sesuatu di mana saya akan mengatur Chrome: Ceko, terminal: Inggris, Spotify: Inggris, ...

Grongor
sumber
Di "Entri Teks" ada opsi "Izinkan sumber yang berbeda untuk setiap jendela". Mungkin langkah ke arah yang benar untuk Anda.
Gunnar Hjalmarsson
Ya, terima kasih, saya tahu tentang itu. Ini adalah langkah yang perlu saya katakan tetapi sayangnya bukan apa yang ingin saya capai. Bagaimanapun, terima kasih.
Grongor
Ada cara scripting. Anda hanya perlu 3 aplikasi itu atau ada yang lain? Tergantung pada seberapa fleksibel Anda menginginkan skrip, mungkin saya butuh waktu lebih atau lebih sedikit untuk menulisnya
Sergiy Kolodyazhnyy
@JacobVlijm Kedengarannya seperti pekerjaan bagus untuk python;)
Sergiy Kolodyazhnyy
Diposting jawaban. Biarkan saya tahu apa yang Anda pikirkan
Sergiy Kolodyazhnyy

Jawaban:

6

pengantar

Skrip di bawah ini menetapkan bahasa untuk setiap program yang ditentukan pengguna, sesuai dengan posisi bahasa itu di menu bahasa. Misalnya, jika pesanan saya adalah: Inggris (1), Cina (2), dan Rusia (3), saya dapat mengatur Firefox untuk memiliki bahasa 2, terminal untuk memiliki bahasa 1, dan LibreOffice untuk memiliki bahasa 3.

Skrip terdiri dari dua bagian: bagian pertama adalah skrip aktual yang berfungsi, skrip kedua berfungsi sebagai elemen pengontrol. Idenya adalah untuk menjalankan skrip pengaturan bahasa sebagai aplikasi start-up dan kapan pun Anda perlu mengubah bahasa secara manual - klik dua kali pintasan ke skrip pengontrol.

Prasyarat

  1. Instal wmctrlprogram dengan sudo apt-get install wmctrl.

Naskah

#!/bin/sh
# Author: Serg Kolo
# Date: August 4, 2015
# Description: This script forces assigned input languages
#              for specific windows
# Version:2

# Use this part to set programs and their respective languages
# PROG_CLASS or a running window can be found with the
# wmctrl -lx command
# If you want to add another program to the list, 
# follow the template PROG_CLASS_num=window.Class
# and bellow that $LANGnum=num


PROG_CLASS_1=gedit.Gedit
LANG1=2

PROG_CLASS_2=gnome-terminal-server.Gnome-terminal
LANG2=0

PROG_CLASS_3=Navigator.Firefox
LANG3=1


# While loop below gets the job done. 
# If you need to send languages for more programs -  copy  
# the first entry and replace  $PROG_CLASS_1 with $PROG_CLASS_num
# where num is respective number of a program
# Replace $LANGnum with the respective language number. After the "="
# post positional number of the language you want to use. 
# Remember the count starts from 0

while [ 1 ];do
  WM_CLASS=$(wmctrl -lx | awk -v search=$(printf %x $(xdotool getactivewindow)) '{ if($1~search) print $3 }' )
  CURRENT=$(gsettings get org.gnome.desktop.input-sources current| awk '{print $2}')
    case  $WM_CLASS in

      $PROG_CLASS_1)  
        if [ $CURRENT -ne  $LANG1 ];then
          gsettings set org.gnome.desktop.input-sources current $LANG1
        fi
      ;;

      $PROG_CLASS_2) 
        if [ $CURRENT -ne  $LANG2 ];then
          gsettings set org.gnome.desktop.input-sources current $LANG2
        fi  
      ;;

       $PROG_CLASS_3) 
         if [ $CURRENT -ne  $LANG3 ];then
           gsettings set org.gnome.desktop.input-sources current $LANG3
         fi  
        ;;
    esac

    sleep 0.250

done

Script Pengendali

#!/bin/sh
# set -x
# Author: Serg Kolo
# Date: August 8, 2015
# Description: Controller script for set-lang.sh script
# Allows pausing and resuming execution of set-lang.sh
STATUS=$(ps -o stat -p $(pgrep -o  set-lang.sh) | awk '{getline;print }')

case $STATUS in
    T) kill -CONT $(pgrep set-lang.sh) 
       notify-send 'RESUMED'
    ;;

    S) kill -STOP $(pgrep set-lang.sh)
       notify-send 'STOPED'
    ;;

    *) exit ;;
esac 

File peluncur (.desktop) untuk skrip set-lang.sh

[Desktop Entry]
Name=set-lang.sh
Comment=Script to set languages
Exec=/home/yourusername/bin/set-lang.sh
Type=Application
StartupNotify=true
Terminal=false

File peluncur (.desktop) untuk set-lang-controller.sh

[Desktop Entry]
Name=lang-control
Comment=Shortcut to controlling script
Exec=/home/yourusername/bin/set-lang-control.sh
Type=Application
StartupNotify=true
Terminal=false

Membuat skrip berfungsi

  1. Buat folder di direktori home Anda bernama bin. Anda dapat melakukannya di manajer file atau menggunakan perintah mkdir $HOME/bindi terminal
  2. Dalam binfolder buat dua file: set-lang.shdan set-lang-control.sh. Simpan skrip ke set-lang.shdan skrip pengontrol ke set-lang-control.sh. Jadikan kedua skrip dapat dieksekusisudo chmod +x $HOME/bin/set-lang-control.sh $HOME/bin/set-lang.sh
  3. Buat dua .desktopfile. Satu adalah set-lang.desktop. Harus ditempatkan di .config/autostartdirektori tersembunyi . Yang kedua adalah set-lang-controller.desktop, bisa diletakkan di binfolder Anda . Selanjutnya seret dan sematkan ke peluncur set-lang-controller.desktopfile. Ini akan menjadi jalan pintas untuk menghentikan sementara dan melanjutkan eksekusi skrip.

Perhatikan bahwa baris tersebut Exec=harus diubah agar nama pengguna Anda yang sebenarnya ada di jalur ke skrip (karena itu adalah direktori home Anda yang sebenarnya). Misalnya, milik sayaExec=/home/serg/bin/set-lang.sh

Penjelasan dan penyesuaian:

Script itu sendiri berjalan dalam infinite while dan memeriksa jendela aktif saat ini. Jika jendela aktif saat ini cocok dengan salah satu opsi dalam struktur kasus, kami beralih ke bahasa yang sesuai. Untuk menghindari pengaturan konstan, setiap bagian dari struktur case memiliki pernyataan if yang memeriksa apakah bahasa telah diatur ke nilai yang diinginkan.

Mengklik ganda pada peluncur untuk set-lang-controller.shakan memeriksa status set-lang.shskrip; jika skrip sedang berjalan - skrip akan dijeda, dan jika skrip dijeda akan dilanjutkan. Pemberitahuan akan ditampilkan dengan pesan yang sesuai.

Untuk menyesuaikan skrip, Anda dapat membuka aplikasi yang diinginkan, menjalankan wmctrl -lxdan mencatat kolom ketiga - kelas jendela. Output sampel:

$ wmctrl -lx | awk '$4="***" {print}'                                                                                                            
0x02c00007 0 gnome-terminal-server.Gnome-terminal *** Terminal
0x03a0000a 0 desktop_window.Nautilus *** Desktop
0x04a00002 0 N/A *** XdndCollectionWindowImp
0x04a00005 0 N/A *** unity-launcher
0x04a00008 0 N/A *** unity-panel
0x04a0000b 0 N/A *** unity-dash
0x04a0000c 0 N/A *** Hud
0x012000a6 0 Navigator.Firefox *** unity - Assign default keyboard language per-application - Ask Ubuntu - Mozilla Firefox

Pilih kelas jendela yang sesuai untuk setiap program. Selanjutnya, buka bagian skrip yang memungkinkan penyesuaian dan tambahkan dua entri untuk PROG_CLASS dan LANG. Selanjutnya tambahkan entri yang sesuai dalam struktur kasus.

Misalnya, jika saya ingin menambahkan, LibreOffice's Writer, saya membuka jendela LibreOffice Writer, pergi ke terminal dan jalankan wmctrl -lx. Ini akan memberi tahu saya bahwa jendela Writer memiliki kelas libreoffice.libreoffice-writer. Selanjutnya saya akan pergi ke script, tambahkan PROG_CLASS_4=libreoffice.libreoffice-writerdan LANG4=3di area yang sesuai. Perhatikan nomor yang cocok 4. Selanjutnya, pergi ke struktur kasus, dan tambahkan entri berikut antara yang terakhir ;;dan esac:

$PROG_CLASS_4) 
  if [ $CURRENT -ne  $LANG4 ];then
    gsettings set org.gnome.desktop.input-sources current $LANG4
  fi  
;;

Sekali lagi, perhatikan tanda $ dan nomor yang cocok 4.

Juga, jika skrip berjalan sebagai item autostart dan Anda ingin menghentikannya sementara untuk menyesuaikannya, gunakan pkill set-lang.shdan lanjutkan dengannohup set-lang.sh > /dev/null 2&>1 &

Catatan kecil: cara lain untuk mengetahui kelas jendela untuk suatu program (hal-hal yang berjalan sebelum braket putaran tunggal dalam struktur kasus) adalah dengan menggunakan ini xpropdan awkoneliner:xprop | awk '/WM_CLASS/ {gsub(/"/," "); print $3"."$5}

Sergiy Kolodyazhnyy
sumber
Terima kasih, ini awal yang bagus. Satu-satunya masalah (tetapi utama) adalah bahwa saya tidak akan dapat beralih bahasa dalam aplikasi tersebut. Script hanya akan menimpa pengaturan saya sepanjang waktu. Saya ingin dapat mengganti bahasa di windows itu juga. Jadi mungkin tambahkan beberapa pemeriksaan untuk aplikasi pid dan bahasa paksa hanya pertama kali atau sesuatu seperti itu?
grongor
Saya juga lebih suka bahwa skrip ini akan menjadi event-driven, bukan berbasis loop. Ini bukan masalah besar tapi saya akan sangat menghargai jika Anda bisa menyediakan cara-kecil untuk mendapatkan ini bekerja dengan dbus atau sesuatu (jika mungkin).
grongor
@ GRNNGoR jadi saya sudah memikirkannya sebentar, dan sejauh ini saya tidak melihat cara untuk menjeda skrip kecuali kill -STOP $(pgrep set-lang.sh)dan kemudian melanjutkan skrip dengan kill -CONT $(pgrep set-lang.sh). Dengan begitu Anda dapat menjeda, beralih bahasa secara normal, dan kemudian melanjutkan.
Sergiy Kolodyazhnyy
Pikiran cepat yang saya miliki adalah bahwa mungkin menggunakan cara pintas keyboard untuk dua perintah mungkin cara untuk melakukannya, tapi saya belum mengujinya, hanya teori sejauh ini. Akan menguji besok setelah saya cukup tidur dan melaporkan kembali :) Beritahu saya jika ini akan menjadi ide yang dapat diterima
Sergiy Kolodyazhnyy
1
+1 untuk pekerjaan hebat dan menyeluruh! Dua hal kecil yang ingin saya sebutkan: executable in ~/bintidak memerlukan path (atau ekstensi, karena itu $PATHsetelah login ulang, lihat: lintian.debian.org/tags/script-with-language-extension .html ), dan Anda dapat menggabungkan stop / start dalam satu .desktopfile; baik dalam daftar cepat atau fungsi sakelar. terlihat cukup sempurna untukku.
Jacob Vlijm
1

Anda dapat menginstalnya gxneurdengan menjalankan

sudo apt-get install gxneur

Perangkat lunak ini dapat secara otomatis beralih tata letak, tetapi tidak sempurna dengan itu.

Tetapi memiliki alat yang sangat bagus untuk mengatur switch tata letak manual.

Anda dapat melakukan apa yang Anda inginkan. Untuk mengatur tata letak spesifik untuk aplikasi tertentu.

Pilot6
sumber
0

Script di bawah ini adalah versi yang diedit dari ini , yang diposting sebagai solusi serupa untuk satu aplikasi (gnome-terminal ) beberapa waktu lalu.

Script ini sebagian ditulis ulang untuk pertanyaan ini, untuk dapat menggunakannya untuk secara otomatis mengatur bahasa untuk beberapa aplikasi.

Cara menggunakan dalam praktik; secara otomatis ingat mengatur bahasa per aplikasi

Jika skrip dimulai untuk pertama kalinya, bahasa saat ini dianggap sebagai bahasa default, yang diingat dalam file tersembunyi: ~/.lang_set .

Maka penggunaannya sederhana: jika Anda menjalankan mis geditdi jendela paling depan, dan mengatur bahasa yang berbeda, bahasa itu secara otomatis terhubung geditsejak saat itu, sampai Anda mengubah bahasa lagi dengangedit di depan.

Jumlah bahasa / aplikasi tertentu pada prinsipnya tidak terbatas; jalankan saja aplikasi dan atur bahasa dengan jendela aplikasi di depan. Aplikasi akan secara otomatis diatur dan diingat tanpa mengedit kode.

Didorong acara?

Meskipun skrip berjalan dalam satu lingkaran, konsumsi sumber daya minimal. Event driven berarti acara tersebut adalah perubahan di jendela paling depan. Saya tidak melihat opsi lain selain "memata-matai" jendela paling depan selain memeriksa satu lingkaran.

Naskah

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

key = [
    "org.gnome.desktop.input-sources",
    "gsettings get ", "gsettings set ",
    " sources", " current",
    ]

prev = os.environ["HOME"]+"/.lang_set"

def get(cmd):
    return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")

def get_front():
    # produce the frontmost application
    try:
        focus = str(hex(int(get("xdotool getwindowfocus").strip())))
        front = focus[:2]+"0"+focus[2:]
        cmd = "wmctrl -lp"
        w_list = subprocess.check_output(["/bin/bash", "-c",cmd]).decode("utf-8")
        w_match = [w for w in w_list.splitlines() if front in w][0].split()[2]
        application = get("ps -p "+w_match+" -o comm=").strip()
        # fix for 15.04, where the process name of gnome-terminal varies
        application = "gnome-terminal" if "gnome-terminal" in application else application
        return application
    except subprocess.CalledProcessError:
        return None

def get_lang():
    # get the currently running language (output = string)
    curr_n = int(get(key[1]+key[0]+key[4]).strip().split()[-1])
    return str(eval(get(key[1]+key[0]+key[3]))[curr_n])

def read_prev(application):
    # reads the possibly set languages for general and specific use (list)
    if not os.path.exists(prev):
        currlang = get_lang()
        open(prev, "wt").write("default "+currlang+"\n"+application+" "+currlang)
        return [currlang, currlang]
    else:
        return [l.strip() for l in open(prev).readlines()]

def write_changed(application, lang):
    changelist = read_prev(front_2)
    try:
        match = changelist.index([l for l in changelist if application in l][0])
        changelist[match] = application+" "+lang+"\n"
    except IndexError:
        changelist.append(application+" "+lang+"\n")
    open(prev, "wt").write(("\n").join(changelist))

def set_lang(lang):
    # set the currently used language (input = string)
    lang_i = eval(get(key[1]+key[0]+key[3])).index(eval(lang))  
    cmd = key[2]+key[0]+key[4]+" "+str(lang_i)
    subprocess.Popen(["/bin/bash", "-c", cmd])

front_1 = get_front(); lang_1 = get_lang()

while True:
    time.sleep(1)
    front_2 = get_front(); lang_2 = get_lang()
    if front_2 != None:
        if front_2 != front_1:
            try:
                setlist = read_prev(front_2)
                match = [l for l in setlist if front_2 in l][0]
            except IndexError:
                match = [l for l in setlist if "default" in l][0]
                set_lang(match[match.find(" ")+1:])            
        elif lang_2 != lang_1:
            write_changed(front_2, lang_2)
    front_1 = front_2; lang_1 = lang_2

Cara mengatur

  1. Script menggunakan keduanya xdotooldan wmctrl:

    sudo apt-get install wmctrl xdotool
    
  2. Salin skrip di atas ke dalam file kosong, simpan sebagai set_language.py

  3. Tes-jalankan dengan perintah:

    python3 /path/to/set_language.py
    
  4. Jika semua berfungsi seperti yang diharapkan, tambahkan ke Aplikasi Startup: Tambah ke Aplikasi Startup: Dash> Aplikasi Startup> Tambah. Tambahkan perintah:

    python3 /path/to/set_language.py
    
Yakub Vlijm
sumber
Satu ukuran cocok untuk semua! +1
Fabby
Hai terima kasih banyak untuk ini, saya akan segera memeriksanya dan memberi tahu Anda bagaimana perasaan saya tentang hal itu :)
grongor