กำหนดภาษาแป้นพิมพ์เริ่มต้นสำหรับแต่ละแอปพลิเคชัน


11

เป็นไปได้หรือไม่ที่จะกำหนดภาษาแป้นพิมพ์เริ่มต้นสำหรับแอปพลิเคชันเฉพาะ ฉันรู้ว่ามีตัวเลือกให้เริ่มแอปพลิเคชันด้วยภาษาของแป้นพิมพ์เริ่มต้นเสมอ แต่นี่ไม่ใช่สิ่งที่ฉันต้องการ

ฉันกำลังมองหาบางอย่างที่คล้ายกับ "พื้นที่ทำงานคงที่" ซึ่งคุณสามารถตั้งค่าโดยใช้ CompizConfig (คุณตั้งค่า Chrome ให้เปิดเสมอที่ X1Y1, เทอร์มินัลที่ X2Y1 เป็นต้น) บางสิ่งที่ฉันจะตั้งค่า Chrome: เช็ก, เทอร์มินัล: อังกฤษ, Spotify: อังกฤษ, ...


ใน "การป้อนข้อความ" มีตัวเลือก "อนุญาตแหล่งข้อมูลที่แตกต่างกันสำหรับแต่ละหน้าต่าง" อาจเป็นขั้นตอนในทิศทางที่ถูกต้องสำหรับคุณ
Gunnar Hjalmarsson

ใช่ขอบคุณฉันรู้เกี่ยวกับสิ่งนั้น นี่เป็นขั้นตอนที่จำเป็นที่ฉันจะพูด แต่น่าเสียดายที่ไม่ใช่สิ่งที่ฉันต้องการบรรลุ ขอบคุณอยู่ดี
grongor

มีวิธีการเขียนสคริปต์ คุณต้องการแอพทั้งสามนี้หรือมีแอปอื่นอยู่ใช่ไหม ขึ้นอยู่กับว่าคุณต้องการให้สคริปต์ยืดหยุ่นเพียงใดมันอาจใช้เวลามากขึ้นหรือน้อยลงในการเขียนสคริปต์
Sergiy Kolodyazhnyy

@JacobVlijm เสียงเหมือนงานที่ดีอีกอย่างสำหรับ python;)
Sergiy Kolodyazhnyy

โพสต์คำตอบ แจ้งให้เราทราบว่าคุณคิดอย่างไร
Sergiy Kolodyazhnyy

คำตอบ:


6

บทนำ

ซอลเบลโลว์สคริปต์ตั้งค่าภาษาสำหรับแต่ละโปรแกรมที่ผู้ใช้กำหนดตามตำแหน่งของภาษานั้นในเมนูภาษา ตัวอย่างเช่นหากคำสั่งของฉันคือ: อังกฤษ (1), จีน (2) และรัสเซีย (3) ฉันสามารถตั้งค่า Firefox ให้มีภาษา 2 เทอร์มินัลให้มีภาษา 1 และ LibreOffice มีภาษา 3

สคริปต์มีสองส่วน: ส่วนที่หนึ่งเป็นสคริปต์จริงที่ทำงานได้สคริปต์ที่สองทำหน้าที่เป็นองค์ประกอบควบคุม แนวคิดคือการเรียกใช้สคริปต์การตั้งค่าภาษาเป็นแอปพลิเคชันเริ่มต้นและเมื่อใดก็ตามที่คุณต้องการเปลี่ยนภาษาด้วยตนเอง - ดับเบิลคลิกที่ทางลัดไปยังสคริปต์ควบคุม

requisites ก่อน

  1. ติดตั้งโปรแกรมwmctrlsudo apt-get install wmctrl

ต้นฉบับ

#!/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

สคริปต์ควบคุม

#!/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 

ไฟล์ Launcher (.desktop) สำหรับสคริปต์ 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

ไฟล์ Launcher (.desktop) สำหรับ 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

ทำให้สคริปต์ทำงานได้

  1. binสร้างโฟลเดอร์ในไดเรกทอรีที่บ้านของคุณเรียกว่า คุณสามารถทำได้ในตัวจัดการไฟล์หรือใช้คำสั่งmkdir $HOME/binใน terminal
  2. ในbinโฟลเดอร์ที่สร้างสองไฟล์: และset-lang.sh set-lang-control.shบันทึกสคริปต์และสคริปต์ที่จะควบคุมset-lang.sh set-lang-control.shทำให้สคริปต์ทั้งสองทำงานได้ด้วยsudo chmod +x $HOME/bin/set-lang-control.sh $HOME/bin/set-lang.sh
  3. สร้างสอง.desktopไฟล์ set-lang.desktopหนึ่งในนั้นคือ จะต้องอยู่ใน.config/autostartไดเรกทอรีที่ซ่อนอยู่ สิ่งที่สองคือset-lang-controller.desktopอาจถูกวางไว้ในbinโฟลเดอร์ของคุณ จากนั้นลากและปักหมุดไปที่ตัวเรียกใช้set-lang-controller.desktopไฟล์ นี่จะเป็นทางลัดสำหรับการหยุดชั่วคราวและเริ่มการทำงานของสคริปต์ต่อไปชั่วคราว

โปรดทราบว่าExec=จะต้องแก้ไขบรรทัดเพื่อให้มีชื่อผู้ใช้จริงของคุณในพา ธ ไปยังสคริปต์ (เนื่องจากเป็นไดเรกทอรีบ้านที่แท้จริงของคุณ) ตัวอย่างเช่นของฉันจะเป็นExec=/home/serg/bin/set-lang.sh

คำอธิบายและการปรับแต่ง:

สคริปต์จะทำงานแบบไม่สิ้นสุดในขณะที่วนซ้ำและตรวจสอบหน้าต่างปัจจุบันที่ใช้งานอยู่ หากหน้าต่างที่ใช้งานในปัจจุบันตรงกับหนึ่งในตัวเลือกในโครงสร้างเคสเราจะเปลี่ยนเป็นภาษาที่เหมาะสม เพื่อหลีกเลี่ยงการตั้งค่าคงที่แต่ละส่วนของโครงสร้างเคสจะมีคำสั่งที่ตรวจสอบว่าภาษานั้นถูกตั้งค่าเป็นค่าที่ต้องการหรือไม่

การดับเบิลคลิกที่ตัวเรียกใช้สำหรับset-lang-controller.shจะตรวจสอบสถานะของset-lang.shสคริปต์ หากสคริปต์ทำงาน - สคริปต์จะหยุดชั่วคราวและหากสคริปต์หยุดชั่วคราวสคริปต์จะทำงานต่อ การแจ้งเตือนจะแสดงพร้อมข้อความที่เหมาะสม

ในการปรับแต่งสคริปต์คุณสามารถเปิดแอปพลิเคชันที่ต้องการเรียกใช้wmctrl -lxและจดบันทึกคอลัมน์ที่สาม - คลาสหน้าต่าง ตัวอย่างผลลัพธ์:

$ 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

เลือกคลาสหน้าต่างที่เหมาะสมสำหรับแต่ละโปรแกรม จากนั้นไปที่ส่วนของสคริปต์ที่อนุญาตให้ปรับแต่งและเพิ่มสองรายการสำหรับ PROG_CLASS และ LANG ถัดไปเพิ่มรายการที่เหมาะสมในโครงสร้างเคส

ตัวอย่างเช่นถ้าผมต้องการที่จะเพิ่มนักเขียน LibreOffice ผมเปิดหน้าต่างเขียน LibreOffice wmctrl -lxไปยังสถานีและเรียกใช้ libreoffice.libreoffice-writerมันจะบอกฉันว่าหน้าต่างเขียนมีระดับ ต่อไปฉันจะไปที่สคริปต์เพิ่มPROG_CLASS_4=libreoffice.libreoffice-writerและLANG4=3ในพื้นที่ที่เหมาะสม สังเกตการจับคู่หมายเลข 4 ถัดไปไปที่โครงสร้างเคสและเพิ่มรายการต่อไปนี้ระหว่างล่าสุด;;และesac:

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

สังเกตอีกครั้งว่าเครื่องหมาย $ และหมายเลขที่ตรงกัน 4

นอกจากนี้หากสคริปต์กำลังทำงานเป็นรายการเริ่มอัตโนมัติและคุณต้องการหยุดการกำหนดเองชั่วคราวให้ใช้pkill set-lang.shและดำเนินการต่อด้วยnohup set-lang.sh > /dev/null 2&>1 &

บันทึกย่อขนาดเล็ก: อีกวิธีหนึ่งในการค้นหาคลาสหน้าต่างสำหรับโปรแกรม (สิ่งที่ไปก่อนวงเล็บเหลี่ยมรอบเดียวในโครงสร้างเคส) คือการใช้สิ่งนี้xpropและawkoneliner:xprop | awk '/WM_CLASS/ {gsub(/"/," "); print $3"."$5}


ขอบคุณนี่เป็นการเริ่มต้นที่ดีทีเดียว ปัญหาเดียว (แต่สำคัญ) คือฉันจะไม่สามารถเปลี่ยนภาษาในแอปพลิเคชันเหล่านั้นได้ สคริปต์จะแทนที่การตั้งค่าของฉันตลอดเวลา ฉันต้องการเปลี่ยนภาษาในหน้าต่างเหล่านั้นด้วย ดังนั้นอาจเพิ่มการตรวจสอบบางอย่างสำหรับ pid ของแอปพลิเคชันและบังคับให้ใช้ภาษาในครั้งแรกเท่านั้นหรืออย่างนั้น
grongor

ฉันยังต้องการให้สคริปต์นี้เป็นตัวขับเคลื่อนกิจกรรมไม่ใช่ตามลูป มันไม่ได้เป็นเรื่องใหญ่ แต่ฉันจะขอบคุณมากถ้าคุณสามารถให้วิธีการเล็ก ๆ น้อย ๆ เพื่อให้การทำงานกับ dbus หรืออะไรบางอย่าง (ถ้าเป็นไปได้)
grongor

@GRoNGoR ดังนั้นฉันจึงคิดเกี่ยวกับเรื่องนี้สักเล็กน้อยและจนถึงตอนนี้ฉันไม่เห็นวิธีที่จะหยุดสคริปต์ชั่วคราวยกเว้นkill -STOP $(pgrep set-lang.sh)จากนั้นกลับมาใช้สคริปต์kill -CONT $(pgrep set-lang.sh)ต่อ ด้วยวิธีนี้คุณสามารถหยุดชั่วคราวสลับภาษาตามปกติแล้วกลับมาทำงานต่อ
Sergiy Kolodyazhnyy

ความคิดที่รวดเร็วที่ฉันมีก็คือบางทีการใช้แป้นพิมพ์ลัดสำหรับคำสั่งสองคำสั่งอาจเป็นวิธีที่ทำได้ แต่ฉันยังไม่ได้ทดสอบ จะทดสอบในวันพรุ่งนี้เมื่อฉันได้รับการนอนหลับที่เพียงพอและรายงานกลับ :) แจ้งให้เราทราบว่านี่จะเป็นความคิดที่ยอมรับได้
Sergiy Kolodyazhnyy

1
+1 สำหรับการทำงานที่ยอดเยี่ยมและทั่วถึง! สองสิ่งเล็ก ๆ ที่ฉันต้องการพูดถึง: executables ~/binไม่จำเป็นต้องใช้พา ธ (หรือส่วนขยายเนื่องจากอยู่$PATHหลังจากเข้าสู่ระบบอีกครั้งโปรดดู: lintian.debian.org/tags/script-with-language-extension .html ) และคุณสามารถรวมการหยุด / เริ่มใน.desktopไฟล์เดียว ไม่ว่าจะเป็นในรายการด่วนหรือฟังก์ชั่นสลับ ดูสวยสมบูรณ์แบบสำหรับฉัน
Jacob Vlijm

1

คุณสามารถติดตั้งgxneurเพื่อใช้งานได้

sudo apt-get install gxneur

ซอฟต์แวร์นี้สามารถเปลี่ยนเลย์เอาต์ได้โดยอัตโนมัติ แต่ไม่สมบูรณ์แบบ

แต่มีเครื่องมือที่ดีมากในการตั้งค่าสวิตช์โครงร่างด้วยตนเอง

คุณสามารถทำสิ่งที่คุณต้องการ เพื่อกำหนดรูปแบบเฉพาะสำหรับแอปพลิเคชันเฉพาะ


0

สคริปต์ด้านล่างนี้เป็นรุ่นที่แก้ไขของคนนี้ที่ถูกโพสต์เป็นวิธีแก้ปัญหาที่คล้ายกันสำหรับโปรแกรมเดียว ( gnome-terminal) ในขณะที่ที่ผ่านมา

สคริปต์ถูกเขียนใหม่บางส่วนสำหรับคำถามนี้เพื่อให้สามารถใช้สำหรับการตั้งค่าภาษาสำหรับหลาย ๆ แอปพลิเคชันโดยอัตโนมัติ

วิธีใช้ในการปฏิบัติ; จำการตั้งค่าภาษาโดยอัตโนมัติต่อแอปพลิเคชัน

~/.lang_setถ้าสคริปต์จะเริ่มต้นเป็นครั้งแรกในภาษาปัจจุบันจะถือว่าเป็นภาษาเริ่มต้นซึ่งเป็นที่จดจำในไฟล์ที่ซ่อนอยู่:

จากนั้นใช้งานง่าย: ถ้าคุณใช้เช่นgeditในด้านหน้าหน้าต่างมากที่สุดและตั้งค่าภาษาที่แตกต่างกันภาษาที่มีการเชื่อมต่อโดยอัตโนมัติgeditจากนั้นจนกว่าคุณจะเปลี่ยนภาษาอีกครั้งกับgeditในด้านหน้า

จำนวนภาษา / แอพพลิเคชั่นที่เฉพาะเจาะจงนั้นไม่ จำกัด ในหลักการ เพียงเรียกใช้แอปพลิเคชันและตั้งค่าภาษาด้วยหน้าต่างแอปพลิเคชันด้านหน้า แอปพลิเคชันจะถูกตั้งค่าและจดจำโดยอัตโนมัติโดยไม่ต้องแก้ไขรหัส

ขับเคลื่อนกิจกรรม

แม้ว่าสคริปต์จะทำงานเป็นวนรอบ แต่ปริมาณการใช้ทรัพยากรก็น้อยมาก การขับเคลื่อนเหตุการณ์จะหมายถึงว่าเหตุการณ์นั้นมีการเปลี่ยนแปลงในหน้าต่างส่วนหน้า ฉันไม่เห็นตัวเลือกอื่นนอกจาก "สอดแนม" สำหรับหน้าต่างส่วนใหญ่ด้านหน้ากว่าการเช็คอินวน

สคริปต์

#!/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

วิธีการตั้งค่า

  1. สคริปต์ใช้ทั้งxdotoolและwmctrl:

    sudo apt-get install wmctrl xdotool
    
  2. คัดลอกสคริปต์ด้านบนลงในไฟล์เปล่าแล้วบันทึกเป็น set_language.py

  3. ทดสอบเรียกใช้โดยคำสั่ง:

    python3 /path/to/set_language.py
    
  4. หากทำงานได้ตามที่คาดไว้ให้เพิ่มลงในแอปพลิเคชันเริ่มต้น: เพิ่มในแอปพลิเคชันเริ่มต้น: Dash> แอปพลิเคชันเริ่มต้น> เพิ่ม เพิ่มคำสั่ง:

    python3 /path/to/set_language.py
    

ขนาดเดียวเหมาะกับทุกคน! +1
Fabby

เฮ้ขอบคุณมากสำหรับเรื่องนี้ผมจะดูเป็นมันเร็ว ๆ นี้และแจ้งให้คุณทราบว่าฉันรู้สึกอย่างไรเกี่ยวกับเรื่องนี้ :)
grongor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.