// ==UserScript== // @name STS Helper // @author 7-elephant // @namespace iFantz7E.StsHelper // @version 2.73 // @description In Steam Translation Server, add many features to make translate easier. // @match *://translation.steampowered.com/* // @icon https://translation.steampowered.com/public/favicon.ico // @run-at document-start // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @grant GM_setClipboard // @license GPL-3.0-only // @copyright 2014, 7-elephant // @supportURL https://steamcommunity.com/id/7-elephant/ // @contributionURL https://www.paypal.me/iFantz7E // @downloadURL https://update.greasyfork.icu/scripts/2250/STS%20Helper.user.js // @updateURL https://update.greasyfork.icu/scripts/2250/STS%20Helper.meta.js // ==/UserScript== // License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html // Compatibility: Firefox 14+ from Mutation Observer // Since 4 Feb 2014 // http://userscripts.org/scripts/show/325610 // https://greasyfork.org/scripts/2250-sts-helper/ (function () { "use strict"; // jshint multistr:true function initStyle() { GM_addStyle (" \ /* STSH Modify CSS */ \ body { color: #acacac; } \ #logout { \ position: fixed; z-index: 1001; right: 12px; top: 10px; \ line-height: 24px; text-align: right; } \ input[type='button'], input[type='submit'] { \ cursor: pointer; padding: 1px 9px; } \ input[type='button']:disabled, input[type='submit']:disabled { \ cursor: default; color: #777; } \ #suggestionmain > div:nth-child(4) > form:nth-child(2) > div:nth-child(1) { \ text-align: left; } \ .lbAction > div > input[value^='SUBMIT'] { \ width: 670px; height: 30px; border-color: #777 #333 #777 #777; } \ .lbAction > div > input[value^='SUBMIT'][disabled] { border-color: #777; } \ .lbAction > div > input[value^='RESUBMIT'] { \ width: 561px; height: 30px; border-color: #777 #333 #777 #777; } \ .lbAction > div > input[value='CANCEL'] { \ width: 100px; height: 30px; margin-right: 5px; } \ form.lbAction:nth-child(1) > div:nth-child(2) > input:nth-child(1) { \ width: 90%; margin-top: 5px; } \ .suggestion .lbAction textarea { \ max-width: 700px !important; min-height: 50px; } \ .progress td { vertical-align: top; } \ div#suggestions_nav { \ z-index: 3; position: absolute; width: 440px; \ left: 543px; top: 2px; text-align: right; line-height: 24px; \ color: #E1E1E1; } \ #suggestionmain .smallcopy { width: 855px; min-height: 70px; max-height: 70px; } \ #suggestionmain .progress { margin-top: -12px; } \ #suggestionmain > div[style='padding-left: 10px;'] { padding-left: 6px !important; } \ #suggestions_box { margin-top: 1px !important; position: relative; z-index: 20; } \ #suggestions_iframe { min-height: 100px !important; } \ #keylist td:nth-child(1) > div { \ background-image: none !important; min-height: 43px; } \ #keylist tr:nth-child(2n) > td:nth-child(1) > div { \ background-color: #060606 !important; } \ #keylist tr:nth-child(2n) > td:nth-child(1) > div:hover { \ background-color: #0D0D0D !important; } \ #keylist td:nth-child(1) > div:hover { \ background-repeat: no-repeat; background-position: center; \ background-color: #0D0D0D !important; \ background-image: url('./public/images/row_over.gif') !important; } \ #keylist td.progress { \ color: #fff; max-width: 430px; overflow: hidden; \ text-overflow: ellipsis; white-space: nowrap; } \ .progress h1 { display: inline-block; } \ div#suggestions_box iframe { background-color: #111 !important; } \ .suggestions_list { border-right: 0px none; } \ .suggestions_list:nth-child(2) { border: 0px none; } \ .suggestion { \ resize: both; overflow-x: hidden; overflow-y: auto; \ border: 1px solid #505050; border-top: none; \ max-width: 953px; min-width: 200px; min-height: 50px; } \ .suggestion:first-child { border-top: 1px solid #505050; } \ .suggestion_signature { font-family: Verdana; margin-top: 4px; } \ .suggestion_signature input:disabled { color: #777 !important; } \ .lbAction input[value~='COMMENT'] { \ vertical-align: top; margin-top: 1px; height: 52px; } \ .lbAction input[value~='DISCUSS'] { \ vertical-align: top; margin-top: 1px; height: 21px; top: 0px !important; } \ #votes_container a[title='not translated'] { background-color: #333; } \ #suggestion_value_new { min-height: 84px; max-width: 960px; min-width: 200px; overflow-y: auto; } \ #hours > table > tbody > tr:nth-child(2) > th:nth-child(1) { width: 106px; text-align: center; } \ #hours > table > tbody > tr:nth-child(2) > th:nth-child(3) { text-align: center; } \ #hours > table > tbody > tr:nth-child(2) > th:nth-child(4) { text-align: center; } \ #hours > table > tbody > tr > td:nth-child(1) { padding-right: 4px; } \ #hours > table input[name*='[remarks]'] { width: 520px; } \ #hours > table input[name*='[hours]'] { width: 100px; } \ #hours > table input[name*='[minutes]'] { width: 100px; } \ #suggestions_box_outer { overflow: hidden !important; } \ #add_to_discussion { height: 19px; min-height: 19px; } \ .gradienttable td > div { top: 1px !important; } \ .copysmall > td:nth-child(1) { \ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; \ display: inline-block; width: 430px; direction: ltr; } \ div:hover > table > tbody > tr.copysmall > td:nth-child(1) { \ direction: rtl; text-shadow: 1px 1px 1px #0D0D0D;} \ #search input[type='radio'], #search input[type='checkbox'] \ , #search button, #search label { cursor: pointer; } \ .suggestion_error { max-width: 600px; margin-left: 80px; } \ #country_list_id + #hidethis { display: block; margin-top: 8px; } \ .row0:nth-child(odd), .row1:nth-child(odd), .row-1:nth-child(odd), .row-9:nth-child(odd), .row10:nth-child(odd) { \ background-color: #161616; } \ .row0:nth-child(even), .row1:nth-child(even), .row-1:nth-child(even), .row-9:nth-child(even), .row10:nth-child(even) { \ background-color: #202020; } \ .row2:nth-child(odd) { background-color: #1C2117; } \ .row2:nth-child(even) { background-color: #22291B; } \ #replacementstatus { \ top: 0px !important; left: 176px !important; \ display: block !important; opacity: 1.0 !important; } \ a + br + #replacementstatus { left: 326px !important; } \ #keylist_container { margin-left: 10px; } \ img[src='public/images/hr.gif'] { background-image: url('./public/images/hr.gif'); } \ "); GM_addStyle (" \ /* STSH Main CSS */ \ .stsh_body_crop { overflow-x: hidden; } \ .stsh_btn { width: 90px; } \ .stsh_btn_med { min-width: 112px; } \ .stsh_btn_long { min-width: 136px; } \ .stsh_btn_short { min-width: 66px; } \ .stsh_btn_right { position: relative; float: right; } \ .stsh_text_right { \ position: relative; float: right; \ display: block; margin-right: 4px; text-transform: none; \ font-size: 13px; font-style: normal; padding-top: 2px; } \ .stsh_border_left { border-right-color: #333 !important; } \ .stsh_border_right { border-left-color: #333 !important; } \ .stsh_border_center { border-left-color: #333 !important; border-right-color: #333 !important; } \ .stsh_border_top { border-bottom-color: #333 !important; } \ .stsh_border_middle { border-top-color: #333 !important; } \ .stsh_border_bottom { border-top-color: #333 !important; border-bottom-color: #333 !important; } \ .stsh_suggestion_header { color: #A4B23C; } \ .stsh_suggestion_comment:before { background-color: #E15417 !important; } \ .stsh_suggestion_pending:before { background-color: #DDD !important; } \ .stsh_suggestion_approved:before { background-color: #A4B23C !important; } \ .stsh_suggestion_declined:before { background-color: #F22 !important; } \ .stsh_suggestion_applied:before { background-color: #2EBCEB !important; } \ .stsh_suggestion_removed:before { background-color: #777 !important; } \ .stsh_suggestion { list-style: none; } \ .stsh_suggestion:before { \ content: ''; display: inline-block; position: relative; height: 6px; width: 6px; \ border-radius: 3px; background-clip: padding-box; margin-right: -6px; \ top: -1px; left: -12px; background-color: green; }\ #stsh_frame { \ text-align: center; position: fixed; z-index: 10; \ top: 100px; left: 50%; margin-left: -322px;} \ #stsh_frame_sub { \ background-color: #111; width: 600px; display: inline-block; \ padding: 20px; border: 2px solid #cf9e5f; } \ .stsh_blue { color: #2EBCEB; } \ .stsh_blue_light { color: #87BEED; } \ .stsh_blue_light2 { color: #5C80A1; } \ .stsh_blue_dark { color: #1B6A85; } \ .stsh_green { color: #a4b23c !important; } \ .stsh_green_dark { color: #3a482a; } \ .stsh_red { color: #F22; } \ .stsh_red_light { color: #4dc0f0; } \ .stsh_white { color: #e1e1e1; } \ .stsh_grey { color: #777 !important; } \ .stsh_orange { color: #E15417; } \ .stsh_orange_light { color: #CF8B37; } \ .stsh_orange_light2 { color: #EDB687; } \ .stsh_orange_light3 { color: #FFAA40; } \ .stsh_orange_dark { color: #a75124; } \ .stsh_aqua { color: #538583; } \ .stsh_pink { color: pink; } \ .stsh_yellow { color: #E0B816; } \ .stsh_yellow_light { color: #E0CA70; } \ .stsh_greenyellow_light { color: #D1E070; } \ .stsh_purple { color: #a166f4; } \ .stsh_border_green { border-color: #76802B !important; } \ .stsh_border_green_left { border-color: #76802B #474D1A #76802B #76802B !important; } \ .stsh_cursor_notallowed { cursor: not-allowed !important; } \ .stsh_cursor_pointer { cursor: pointer !important; } \ .stsh_cursor_default { cursor: default !important; } \ .stsh_cursor_help { cursor: help !important; } \ .stsh_inline { display: inline; } \ #stsh_showing { \ color: #CCDAD6; position: fixed; z-index: 1001; \ right: 12px; bottom: 12px; text-align: right; line-height: 14px;} \ #stsh_showing_current { \ color: #CCDAD6; position: fixed; z-index: 1001; \ right: 12px; bottom: 28px; text-align: right; line-height: 14px;} \ .stsh_showing_counter { \ display: inline-block; min-width: 60px; text-align: center; } \ .stsh_showing_header { \ color: #CCDAD6; display: inline-block; width: 135px; \ text-align: center; padding-top: 10px; } \ .stsh_showing_group { \ position: fixed; z-index: 3; right: 10px; top: 74px; \ line-height: 24px; text-align: right; } \ .stsh_home_header { color: #CCDAD6; display: inline-block; padding-top: 10px; } \ .stsh_home_group { \ position: fixed; z-index: 3; right: 0px; top: 74px; \ line-height: 24px; text-align: center; width: 164px; } \ .stsh_home_group > div > .stsh_a_button { border-top-color: #333; border-bottom-color: #333; } \ .stsh_home_group > div > .stsh_a_button:first-child { border-top-color: #777; } \ .stsh_home_group > div > .stsh_a_button:last-child { border-bottom-color: #777; } \ .stsh_home_group > div > div > .stsh_a_button { border-top-color: #333; border-bottom-color: #333; } \ .stsh_home_group > div > div > .stsh_a_button:first-child:not(:last-child) { border-right-color: #333; } \ .stsh_home_group > div > div > .stsh_a_button:last-child:not(:first-child) { border-left-color: #333; } \ .stsh_home_group > div > div:first-child > .stsh_a_button { border-top-color: #777; } \ .stsh_home_group > div > div:last-child > .stsh_a_button { border-bottom-color: #777; } \ .stsh_home_group .stsh_a_button { cursor: pointer; } \ .stsh_menu_group { \ position: fixed; z-index: 3; right: 12px; top: 84px; \ line-height: 24px; text-align: right; } \ .stsh_group_space { margin-top: 3px; } \ .stsh_scroll_header { \ color: #CCDAD6; display: inline-block; width: 130px; \ text-align: center; padding-top: 10px; } \ #stsh_specialEvent { position: absolute; z-index: 2; right: 164px; top: 13px; } \ @media screen and (min-width: 1500px) { \ #stsh_specialEvent { position: fixed; } \ } \ .stsh_snapshot { \ position: absolute; top: 320px; left: 790px; \ width: 140px; text-align: center; color: #FFF; } \ .stsh_text_comment_header { vertical-align: top; user-select: none; } \ .stsh_text_comment { vertical-align: top; display: inline-block; max-width: 850px; user-select: text; } \ .stsh_action_approve, .stsh_action_approve_next { color: #A4B23C; } \ .stsh_action_decline, .stsh_action_decline_next { color: #F22; } \ .stsh_action_apply, .stsh_action_apply_next { color: #2EBCEB; } \ #stsh_autoApprove { vertical-align: -2px; margin-left: 15px; margin-right: 1px; } \ .stsh_unselectable { \ -webkit-touch-callout: none !important; \ -webkit-user-select: none !important; \ -khtml-user-select: none !important; \ -moz-user-select: none !important; \ -ms-user-select: none !important; \ user-select: none !important; } \ .stsh_a_button { \ background-color: #1D1D1D; \ font-family: tahoma,arial,helvetica,trebuchet ms,sans-serif; \ color: #E1E1E1; font-size: 13px; border: 1px solid #777; padding: 1px 9px; } \ .stsh_a_button:link, .stsh_a_button:hover, .stsh_a_button:active, .stsh_a_button:visited { \ color: #E1E1E1; text-decoration: none; } \ .stsh_a_button.stsh_btn { \ display: inline-block; padding: 0px; \ height: 19px; line-height: 19px; width: 88px; } \ .stsh_a_button.stsh_btn_short { \ display: inline-block; padding: 0px; \ height: 19px; line-height: 19px; min-width: 54px; } \ .stsh_a_button.stsh_btn_med { \ display: inline-block; padding: 0px; \ height: 19px; line-height: 19px; min-width: 110px; } \ .stsh_a_button.stsh_btn_long { \ display: inline-block; padding: 0px; \ height: 19px; line-height: 19px; min-width: 134px; } \ .stsh_lineCounter_outer { position: relative; } \ .stsh_lineCounter { \ position: absolute; width: 30px; left: -35px; top: -28px; \ line-height: 28px; text-align: right; \ color: #ACACAC; font-size: 9px; text-shadow: 1px 1px 1px #111; } \ .stsh_glossary_term { min-width: 50px; display: inline-block; } \ .stsh_glossary_header { font-family: Verdana; } \ .stsh_glossary_header, .stsh_glossary_header td { color: #DDD; } \ .stsh_glossary_header *, .stsh_glossary_header td * { color: #858585; } \ .stsh_glossary_header > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(4) { \ width: 10px !important; } \ .stsh_comment_img { \ display: block; max-width: 400px; max-height: 225px; \ margin-top: 5px; margin-bottom: 20px; } \ .stsh_comment_img_zoom { cursor: zoom-in; cursor: -webkit-zoom-in; cursor: -moz-zoom-in; } \ .stsh_hours_curDate { color: #A4B23C; } \ .stsh_hours_curDate input { border-color: #A4B23C; } \ .stsh_text_submit_right { \ height: 30px; width: 214px; margin-right: 5px; border-color: #777 #777 #777 #333; } \ .stsh_truncate { \ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; \ display: inline-block; vertical-align: bottom; } \ .stsh_token_name { max-width: 500px; } \ .stsh_token_share { max-width: 600px; font-size: 0.8em; direction: rtl; } \ .stsh_token_share:hover { direction: ltr; } \ .stsh_pad { padding-left: 2px; padding-right: 2px; } \ .stsh_pad_left { padding-left: 4px; } \ .stsh_pad_right { padding-right: 4px; } \ .stsh_margin_left { margin-left: 4px; } \ .stsh_margin_right { margin-right: 4px; } \ .stsh_hidden { display: none !important; } \ table.gradienttable .stsh_curLang td, table.gradienttable .stsh_dst_curLang td \ , table.gradienttable .stsh_dst_curLang th { \ background: transparent \ linear-gradient(to bottom, #171717 0%, rgba(71, 77, 26, 0.66) 40%, #121212 100%) \ repeat scroll 0% 0% !important; } \ .stsh_delta #suggestion_value_new { border-color: #1B6A85; } \ .stsh_delta .stsh_text_submit { \ color: #2EBCEB; border-color: #1B6A85 #083F52 #1B6A85 #1B6A85 !important; } \ .stsh_delta .stsh_text_submit_right { \ color: #2EBCEB; border-color: #1B6A85 #1B6A85 #1B6A85 #083F52 !important; } \ .stsh_delta .suggestions_list, .stsh_delta .suggestion { \ border-color: #083F52 !important; } \ .stsh_usThem tr:nth-child(odd) { background-color: #161616; } \ .stsh_usThem tr:nth-child(even) { background-color: #202020; } \ .stsh_usThem_langCur { background-color: #2F3317 !important; color: #E1E1E1; } \ .stsh_dst_curLang, table.gradienttable .stsh_dst_curLang th, .stsh_dst_curLang a { \ color: #2ebceb; } \ .stsh_text_trn .lbAction textarea { max-width: 450px !important; } \ .stsh_text_trn .lbAction input[value~='COMMENT'] { height: auto; } \ .stsh_text_trn .stsh_text_submit { width: 190px !important; } \ .stsh_text_trn .stsh_text_submit_right { \ width: 184px !important; margin-right: 16px !important; } \ .stsh_text_trn .suggestion { \ color: #858585; border-width: 1px solid; \ margin-top: -2px; padding-top: 0px; } \ .stsh_text_trn .stsh_counter:after { margin-top: 3px; } \ .stsh_text_trn .suggestion_error { \ max-width: 450px; margin-left: 0px; margin-top: 16px; margin-bottom: -14px; } \ .stsh_text_trn #stsh_autoApprove { display: none; } \ .stsh_text_trn .stsh_autoApprove_label { display: none; } \ .stsh_text_trn input[value='+1'] { display: none; } \ .stsh_text_trn #replacementstatus { left: 140px !important; } \ .stsh_text_trn .stsh_autoReplace_notice { margin-top: 14px; padding-left: 88px; } \ .stsh_text_org, .stsh_text_trn { \ min-height: 21px; display: block; max-width: 470px !important; line-height: 17px; word-break: break-word; } \ .stsh_text_org { margin-bottom: 3px; } \ .stsh_text_org img, .stsh_text_trn img { max-width: 100%; max-height: 100%; } \ .stsh_autoLoginOption { display: inline-block; vertical-align: top; line-height: 69px; padding-left: 30px; } \ #stsh_autoLogin { margin-right: 0px; } \ .stsh_moveSuggestionContainer { margin-top: -3px; } \ #stsh_moveSuggestionBox, #stsh_moveSuggestionList { margin-right: 5px; } \ #stsh_hoursCalc_from { width: 130px; } \ #stsh_hoursCalc_to { width: 130px; border-right: 1px #333 solid; } \ #stsh_hoursCalc_toNow { border-left: 1px #333 solid; } \ .stsh_nav_prev { border-right-color: #333; } \ .stsh_nav_next { border-left-color: #333; } \ .stsh_nav_group { display: inline-block; } \ .stsh_nav_group .stsh_a_button { \ display: inline-block; text-align: center; \ line-height: 17px; min-width: 40px; } \ .stsh_nav_group .stsh_a_button:first-child:not(:last-child) { border-right-color: #333; } \ .stsh_nav_group .stsh_a_button:last-child:not(:first-child) { border-left-color: #333; } \ .stsh_nav_group .stsh_a_button:not(:first-child):not(:last-child) { \ border-left-color: #333; border-right-color: #333; } \ .stsh_img_min { max-width: 200px !important; height: auto !important; } \ .stsh_showHidden { \ display: inherit !important; background-color: #1d1d1d; padding: 1px 5px; \ max-height: inherit !important; height: inherit !important; } \ .stsh_discussion_header input[type='button'] { \ padding: 1px 6px; } \ .stsh_counter { display: inline-block; } \ .stsh_counter[data-counter='Char: 0 :: Word: 0 :: Byte: 0'] { display: none; } \ .stsh_counter:after { content: attr(data-counter); position: absolute; \ margin-left: -280px; width: 278px; text-align: right; } \ .stsh_spanStatusOrg, .stsh_spanStatusTrn { display: block; margin-top: -4px; margin-bottom: 8px; } \ .stsh_spanStatusSug { display: block; margin-top: 8px; margin-bottom: 12px; } \ .stsh_autoCopy_header font { color: #a4b23c !important; font-weight: normal; font-family: Verdana;} \ .stsh_glossary_move { color: #e1e1e1; margin-left: 4px; } \ .stsh_sametoken_file { display: inline-block; } \ .stsh_marker { color: #777 !important; display: inline-block; } \ .stsh_sametoken_header .stsh_marker, .stsh_text_comment .stsh_marker { color: #e1e1e1 !important; } \ .stsh_glossary_header .insertword { display: inline-block; } \ .stsh_glossary_header td { padding-left: 16px; padding-right: 6px; } \ .stsh_glossary_header td .stsh_glossary_term { margin-left: -16px; } \ .stsh_profile_count { width: 100px; display: inline-block; text-align: center; } \ .stsh_profile_count_sugg { margin-left: 13px; } \ .stsh_comment_resolved_label { display: block; width: 300px; margin-bottom: 10px; } \ .stsh_comment_resolved { vertical-align: -2px; margin-left: 0px; margin-right: 1px; } \ .stsh_suggestion_comment_detail > strong:first-child, .stsh_comment_resolved_label > strong:first-child { \ min-width: 64px; display: inline-block; } \ .stsh_discussion_text { display: inline; max-width: 850px; overflow-wrap: break-word; } \ .stsh_discussion_text.stsh_discussion_text_long { display: block; margin-left: 20px; } \ .stsh_date_group { text-align: center; } \ .stsh_date_group button { line-height: 19px; } \ .stsh_date_group .stsh_date_cur { border-left-color: #333; border-right-color: #333; \ margin-top: 22px !important; } \ .stsh_date_group .stsh_date_prev { border-right-color: #333; margin-left: 2px; } \ .stsh_date_group .stsh_date_next { border-left-color: #333; } \ .stsh_autoReplace_header { font-family: Verdana; } \ .stsh_autoReplace_instruction { width: 870px; } \ .stsh_autoReplace_text { width: 300px; cursor: auto !important; } \ .stsh_checkbox_label { margin-left: 10px; } \ .stsh_checkbox_label > input[type='checkbox'] { vertical-align: -2px; margin-left: 0px; margin-right: 1px; } \ .stsh_usThem_translation { min-width: 400px; } \ .stsh_page_userActivity .dial { display: none; } \ .stsh_page_userActivity table.curved { border: 2px solid #444; } \ .stsh_page_usAndThem #leftAreaContainer > table > tbody:nth-child(1) > tr > td:nth-child(1) { \ vertical-align: top; } \ .stsh_page_usAndThem #leftAreaContainer > table, \ .stsh_page_usAndThem #leftAreaContainer > table th, \ .stsh_page_usAndThem #leftAreaContainer > table td { \ border: 1px solid #333; border-collapse: collapse; padding: 4px; } \ .stsh_btn_display { border-left-color: #333; border-right-color: #333; } \ .stsh_btn_display:first-child { border-right-color: #777; } \ .stsh_btn_display:last-child { border-left-color: #777; } \ .stsh_autoReplace_notice { text-align: left; padding-left: 208px; } \ a + br + #replacementstatus + br + .stsh_autoReplace_notice { \ text-align: center; padding-left: 0px; } \ .stsh_suggestion_list_empty { \ border-top: 1px solid #505050 !important; border-left: 1px solid #505050 !important; padding-left: 2px; } \ .stsh_suggestion_border_approved { border-color: #76802B !important; border-top: 1px solid; } \ .stsh_suggestion_border_declined { border-color: #720D0D !important; } \ .stsh_suggestion_border_approved + .stsh_suggestion_border_approved { border-top: none; } \ .stsh_action_edit { border-left-color: #333; } \ .stsh_header_org, .stsh_header_trn { width: 484px; position: relative; } \ .stsh_copy_org, .stsh_copy_trn { position: absolute; margin-left: 8px; margin-top: 22px; border-color: #555; } \ .stsh_copy_new { width: 80px; height: 30px; border-left-color: #333; border-right-color: #333; } \ .stsh_copy_sug { border-right-color: #333; } \ .stsh_suggestion_list_header { width: 961px; } \ .stsh_suggestion_list_history { padding-left: 2px; } \ .stsh_suggestion_list_history_related { border-color: #4D6C87; } \ .stsh_page_home font[style='color:#EDB687;'] { padding-right: 4px; } \ .stsh_home_discussion_file { cursor: pointer; } \ .stsh_home_discussion_comment { overflow-wrap: break-word; } \ .stsh_suggestion_list_history_header { user-select: none; } \ @media screen and (max-height: 600px) { .stsh_home_section_scroll { display: none; } } \ .stsh_home_hideOtherLang { margin-left: 16px; margin-top: 10px; width: 152px; } \ "); } var timingInit = { initNameSpace: 100, refreshError: 60000, cleanLinks: 100, removeHorizonScroll: 100, resizeTextNew: 100, improveGlossary: 200, bindLastText: 100, insertAtCaret: 500, pasteLastComment: 250, autoApprove: 2000, pasteLastSuggestion: 300, hideCursor: 3000, expandTextarea: 100, focusModAction: 200, autoReplaceText: 250, findNextUnmatched: 500, openFrame: 1000, improveStatistics: 100, autoLogin: 3000, authSubmit: 3000, bindObserverKeyList: 200, pageUserActivity: 100, disableOnClick: 100, reenableAfterClick: 1000, }; function attachOnLoad(callback) { window.addEventListener("load", function (e) { callback(); }); } function attachOnReady(callback) { document.addEventListener("DOMContentLoaded", function (e) { callback(); }); } function insertBeforeElement(newNode, referenceNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode); } function insertAfterElement(newNode, referenceNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } function removeElement(node) { node.parentElement.removeChild(node); } function getByteCount(str) { str = String(str); var count = 0; for (var i = 0; i < str.length; i++) { var c = str.charCodeAt(i); count += c < 128 ? 1 : c < 2048 ? 2 : c < 65536 ? 3 : c < 2097152 ? 4 : c < 67108864 ? 5 : c < 2147483648 ? 6 : 0; } return count; } function escapeRegExp(str) { if (typeof str === "string") { return str.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); } return ""; } function addKey(eleListener, eleClick, keyCodes, keyName, keyTitleMode, keyModifierName, checkModifierCallback) { /* eleClick: element, query keyCodes: code, name, array keyTitleMode: 0: do nothing 1: append value 2: add title if not exist 4: override title 8: append textContent 16: append textContent of firstElementChild keyModifierName: Ctrl, Ctrl+Shift, Alt */ keyCodes = keyCodes || [0]; keyName = keyName || ""; keyTitleMode = keyTitleMode || 0; keyModifierName = keyModifierName || ""; if (typeof checkModifierCallback !== "function") { checkModifierCallback = function(ev) { return ev.ctrlKey && ev.shiftKey && ev.altKey; }; } if (typeof eleClick === "string") { keyTitleMode = 0; } if (!Array.isArray(keyCodes)) { keyCodes = [keyCodes]; } if (eleListener && eleClick) { // apply title var keyTitle = keyModifierName ? keyModifierName + "+" + keyName : ""; if (keyTitle !== "" && keyTitleMode !== 0) { if ((keyTitleMode & 1) === 1) { // 1: append value if (typeof eleClick.value !== "undefined") { eleClick.value += " (" + keyTitle + ")"; } } if ((keyTitleMode & 2) === 2) { // 2: add title if not exist if (!eleClick.title) { eleClick.title = keyTitle; } } if ((keyTitleMode & 4) === 4) { // 4: override title eleClick.title = keyTitle; } if ((keyTitleMode & 8) === 8) { // 8: append textContent eleClick.textContent += " (" + keyTitle + ")"; } if ((keyTitleMode & 16) === 16) { // 16: append textContent of firstElementChild if (eleClick.firstElementChild) { eleClick.firstElementChild.textContent += " (" + keyTitle + ")"; } } } eleListener.addEventListener("keydown", function (ev) { if (checkModifierCallback(ev)) { var isSameKey = false; for (var i = 0; i < keyCodes.length; i++) { var keyCode = keyCodes[i]; if (typeof keyCode === "number") { isSameKey = (ev.keyCode === keyCode); } else { // Firefox 32+ isSameKey = (typeof ev.code !== "undefined" && ev.code === keyCode) } if (isSameKey) { break; } } if (isSameKey) { ev.preventDefault(); var eleClickCur = null; if (typeof eleClick === "string") { eleClickCur = document.querySelector(eleClick); } else { eleClickCur = eleClick; } if (eleClickCur) { eleClickCur.focus(); eleClickCur.click(); } return false; } } }, true); } } function addKeyCtrl(eleListener, eleClick, keyCode, keyName, keyTitleMode) { addKey(eleListener, eleClick, keyCode, keyName, keyTitleMode, "Ctrl", function(ev) { return ev.ctrlKey && !ev.shiftKey && !ev.altKey; }); } function addKeyCtrlShift(eleListener, eleClick, keyCode, keyName, keyTitleMode) { addKey(eleListener, eleClick, keyCode, keyName, keyTitleMode, "Ctrl+Shift", function(ev) { return ev.ctrlKey && ev.shiftKey && !ev.altKey; }); } function addKeyAlt(eleListener, eleClick, keyCode, keyName, keyTitleMode) { addKey(eleListener, eleClick, keyCode, keyName, keyTitleMode, "Alt", function(ev) { return !ev.ctrlKey && !ev.shiftKey && ev.altKey; }); } function addKeyCtrlEnter(form, input) { addKeyCtrl(form, input, ["Enter", 13], "Enter", 1|2); } function addKeyCtrlShiftEnter(form, input) { addKeyCtrlShift(form, input, ["Enter", 13], "Enter", 1|2); } function disableAfterClick(ele) { ele.addEventListener("click", function (e) { var ele = e.target; var attrClick = ele.getAttribute("onclick"); if (attrClick && attrClick.indexOf("confirm") > -1) { // skip if has confirm return; } var tagName = ele.tagName; if (tagName === "INPUT") { // don't change color after disable var styleCp = window.getComputedStyle(ele); if (styleCp) { ele.style.setProperty("color", styleCp.color, "important"); } setTimeout(function(ele) { ele.disabled = true; }, timingInit.disableOnClick, ele); setTimeout(function(ele) { ele.disabled = false; }, timingInit.reenableAfterClick, ele); } else if (tagName === "IMG") { setTimeout(function(ele) { ele.dataset.stshOldonclick = ele.getAttribute("onclick") || ""; ele.removeAttribute("onclick"); }, timingInit.disableOnClick, ele); setTimeout(function(ele) { ele.setAttribute("onclick", ele.dataset.stshOldonclick); }, timingInit.reenableAfterClick, ele); } else if (tagName === "A") { setTimeout(function(ele) { ele.dataset.stshOldonclick = ele.getAttribute("onclick") || ""; ele.setAttribute("onclick", "return false;"); }, timingInit.disableOnClick, ele); setTimeout(function(ele) { ele.setAttribute("onclick", ele.dataset.stshOldonclick); }, timingInit.reenableAfterClick, ele); } }, true); } function removeAllEventListeners(element) { if (element) { var clone = element.cloneNode(false); while (element.firstChild) { clone.appendChild(element.firstChild); } element.parentNode.replaceChild(clone, element); } } function focusWithoutScroll(selector) { var ele = null; if (selector instanceof HTMLElement) { ele = selector; } else { ele = document.querySelector(selector); } if (ele) { var x = window.scrollX; var y = window.scrollY; ele.focus(); window.scrollTo(x, y); } } function scrollToId(id, offset) { scrollToElement("#" + id, offset); } function scrollToElement(selector, offset) { if (typeof offset === "undefined") { offset = -20; } var ele = null; if (selector) { if (selector instanceof HTMLElement) { ele = selector; } else { ele = document.querySelector(selector); } if (ele) { ele.scrollIntoView(true); window.scrollBy(0, offset); } } } function resizeSuggestionBox() { var script = document.createElement('script'); script.innerHTML = " \ /* STSH JS - resizeSuggestionBox */ \ var stsh_showSuggestionsBox_start = getTimeMs(); \ var stsh_showSuggestionsBox_itv = setIntervalCustom(function() \ { \ var stsh_showSuggestionsBox_isEnd = false; \ var stsh_showSuggestionsBox_cur = getTimeMs(); \ if (typeof showSuggestionsBox !== 'undefined') \ { \ showSuggestionsBox = function(url) \ { \ /* Edit from STS */ \ g_suggestionsBoxIsOpen = true; \ $('suggestions_box_outer').appear( \ { \ duration : 0.1 \ } \ ); \ $('suggestions_iframe').setAttribute('src', url); \ if (!Prototype.Browser.IE) \ { \ $('suggestions_iframe').focus(); \ } \ $('suggestions_iframe').style.height = (document.viewport.getHeight() * 0.99) + 'px'; \ return false; \ }; \ stsh_showSuggestionsBox_isEnd = true; \ } \ if (stsh_showSuggestionsBox_isEnd || stsh_showSuggestionsBox_cur - stsh_showSuggestionsBox_start > 10000) \ { \ clearInterval(stsh_showSuggestionsBox_itv); \ } \ }, 300); \ "; document.head.appendChild(script); window.addEventListener("resize", function() { var iframe = document.querySelector("#suggestions_iframe"); if (iframe) { iframe.style.height = (window.innerHeight * 0.99) + "px"; } }); } function isRally() { var date = new Date(); var year = date.getUTCFullYear(); var month = date.getUTCMonth() + 1; var day = date.getUTCDate(); if ((month > 9) || (month === 9 && day >= 22) || (month === 0 && day <= 2)) { return true; } return false; } function getQueryByName(name, url) { if (!url) { url = (!window.location) ? "" : window.location.search; } name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"); var results = regex.exec(url); var retVal = ""; if (results) { retVal = results[1].replace(/\+/g, " "); try { retVal = decodeURIComponent(retVal); } catch (ex) { console.error("getQueryByName", ex.message); } } return retVal; } function padZero(num, size) { return (1e15 + num + "").slice(-size); } function padZeroHex(num, size) { return ("00000000000000000000000" + num.toString(16)).slice(-size).toUpperCase(); } function randNum(min, max) { return Math.round(Math.random() * (max - min) + min); } function isLastIndex(src, des) { if (src !== null && src !== "" && des !== null && des !== "") { if (src.lastIndexOf(des) === src.length - 1) { return true; } } return false; } function isSpecialChar(ch) { var chCode = -1; if (typeof ch === 'number') { chCode = ch; } else { chCode = ch.charCodeAt(0); } if ((chCode > -1 && chCode < 9) // 0-8 || (chCode > 10 && chCode < 13) // 11-12 || (chCode > 13 && chCode < 32)) // 14-31 { return true; } return false; } function hasSpecialChar(str) { var rgxSpCh = /[\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u000B\u000C\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F]+/; return rgxSpCh.test(str); } function checkSpecialCharMatched(str1, str2) { // return (status, numSp1, numSp2) // status: 0:Match, 1:NotMatch, 2:NotEqual str1 = str1 || ""; str2 = str2 || ""; var strOut1 = ""; var strOut2 = ""; for (var i = 0; i < str1.length; i++) { if (isSpecialChar(str1[i])) { strOut1 += str1[i]; } } for (var i = 0; i < str2.length; i++) { if (isSpecialChar(str2[i])) { strOut2 += str2[i]; } } var retVal = 0; if (strOut1 === strOut2) retVal = 0; else if (strOut1.length === strOut2.length) retVal = 1; else retVal = 2; return new Array(retVal, strOut1.length, strOut2.length); } function countDiacriticalMark(str) { str = str || ""; var rgxDct = /[\u0300-\u036F]/g; var matchDct = str.match(rgxDct); var countDct = matchDct ? matchDct.length : 0; return countDct; } function countDescendantElement(ele) { var countElement = 0; if (ele instanceof Element) { var children = ele.children; countElement = children.length; for (var i = 0; i < children.length; i++) { countElement += countDescendantElement(children[i]); } } return countElement; } function trimSpace(str) { if (str !== null) { return str.replace(/^[ \r\n\t]+/, "").replace(/[ \r\n\t]+$/, ""); } return str; } function trimTab(str) { if (str !== null) { return str.replace(/^[\r\n\t]+/, "").replace(/[\r\n\t]+$/, ""); //.replace(/\t+<\//, "<"); } return str; } function trimTabLeft(str) { if (str !== null) { return str.replace(/^[\r\n\t]+/, ""); } return str; } function trimTabRight(str) { if (str !== null) { return str.replace(/[\r\n\t]+$/, ""); } return str; } function trimElement(ele) { if (ele instanceof Element) { if (!ele.firstElementChild) { ele.textContent = trimTab(ele.textContent); } else { if (ele.firstChild.nodeType === document.TEXT_NODE) { ele.firstChild.textContent = trimTabLeft(ele.firstChild.textContent); } if (ele.lastChild.nodeType === document.TEXT_NODE) { ele.lastChild.textContent = trimTabRight(ele.lastChild.textContent); } } } return ele; } if (!String.prototype.endsWith) { String.prototype.endsWith = function(searchString, position) { var subjectString = this.toString(); if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { position = subjectString.length; } position -= searchString.length; var lastIndex = subjectString.indexOf(searchString, position); return lastIndex !== -1 && lastIndex === position; }; } function reload() { var curHref = window.location.href; var posHashtag = curHref.indexOf("#"); if (posHashtag > -1) { window.location = curHref.substr(0, posHashtag); } else { window.location = curHref; } } function getCookie(c_name) { var c_value = document.cookie; var c_start = c_value.indexOf(" " + c_name + "="); if (c_start === -1) { c_start = c_value.indexOf(c_name + "="); } if (c_start === -1) { c_value = null; } else { c_start = c_value.indexOf("=", c_start) + 1; var c_end = c_value.indexOf(";", c_start); if (c_end === -1) { c_end = c_value.length; } c_value = unescape(c_value.substring(c_start, c_end)); } return c_value; } var isVisible = (function() { var stateKey; var eventKey; var keys = { hidden: "visibilitychange", webkitHidden: "webkitvisibilitychange", mozHidden: "mozvisibilitychange", msHidden: "msvisibilitychange" }; for (stateKey in keys) { if (stateKey in document) { eventKey = keys[stateKey]; break; } } return function(c) { if (c) { document.addEventListener(eventKey, c); } return !document[stateKey]; } })(); function isDstUs(year, month, day, hour) { // Support: 2007 - 2029 // Params: 2016, 3, 1, 15 === 1 Mar 2016 15:00 var isDst = false; try { var y = parseInt(year); var m = parseInt(month); var d = parseInt(day); var h = parseInt(hour); var checkDstUsa = function(dayMar, dayNov, m, d, h) { var isDst = false; if ((m === 3 && d >= dayMar) || (m > 3 && m < 11) || (m === 11 && d <= dayNov)) isDst = true; if ((m === 3 && d === dayMar && h < 2) || (m === 11 && d === dayNov && h >= 2)) isDst = false; return isDst; } if (y === 2007 || y === 2012 || y === 2018 || y === 2029) { isDst = checkDstUsa(11, 4, m, d, h); } else if (y === 2013 || y === 2019 || y === 2024) { isDst = checkDstUsa(10, 3, m, d, h); } else if (y === 2008 || y === 2014 || y === 2025) { isDst = checkDstUsa(9, 2, m, d, h); } else if (y === 2009 || y === 2015 || y === 2020 || y === 2026) { isDst = checkDstUsa(8, 1, m, d, h); } else if (y === 2010 || y === 2021 || y === 2027) { isDst = checkDstUsa(14, 7, m, d, h); } else if (y === 2011 || y === 2016 || y === 2022) { isDst = checkDstUsa(13, 6, m, d, h); } else if (y === 2017 || y === 2023 || y === 2028) { isDst = checkDstUsa(12, 5, m, d, h); } } catch (ex) { console.error("isDstUs", ex.message); } return isDst; } function getDateIsoUs(unixTs) { var dateUs = unixTs ? new Date(unixTs * 1000) : new Date(); dateUs.setTime(dateUs.getTime() - (1000 * 60 * 60 * 8)); // GMT-8 if (isDstUs(dateUs.getUTCFullYear(), dateUs.getUTCMonth() + 1, dateUs.getUTCDate(), dateUs.getUTCHours())) { dateUs.setTime(dateUs.getTime() + (1000 * 60 * 60 * 1)); // GMT-7 } return dateUs.toISOString(); } function getDateUs(unixTs) { return getDateIsoUs(unixTs).substr(0, 10); } function getDateTimeUs(unixTs) { var dateIso = getDateIsoUs(unixTs); return dateIso.substr(0, 10) + " " + dateIso.substr(11, 8); } function getTimeUs(unixTs) { return getDateIsoUs(unixTs).substr(11, 5); } function getDateIsoGmt(unixTs) { var date = unixTs ? new Date(unixTs * 1000) : new Date(); return date.toISOString(); } function getDateGmt(unixTs) { return getDateIsoGmt(unixTs).substr(0, 10); } function getTimeMs(unixTs) { return unixTs ? new Date(unixTs * 1000).getTime() : new Date().getTime(); } function getUnixTimestamp(date) { return parseInt((date ? new Date(date) : new Date()).getTime() / 1000); } var pattUrlTimestamp = { type1: /\?t=[0-9]{6,}\&/g, type2: /\&t=[0-9]{6,}/g, type3: /\?t=[0-9]{6,}/g, type4: /\&[0-9]{6,}\&/g, type5: /\&$/, }; function cleanUrlTimestamp(eles) { if (!eles || !eles.length) return; for (var i = 0; i < eles.length; i++) { var val = ""; var attr = ""; if (eles[i].tagName === "A") { attr = "href"; } else if (eles[i].tagName === "FORM") { attr = "action"; } else if (eles[i].tagName === "DIV") { attr = "onclick"; } else if (eles[i].tagName === "INPUT") { attr = "onclick"; if (eles[i].name === "t") { removeElement(eles[i]); continue; } } var isEdit = false; val = eles[i].getAttribute(attr); if (pattUrlTimestamp.type1.test(val)) { eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type1, "?")); isEdit = true; } else if (pattUrlTimestamp.type2.test(val)) { eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type2, "")); isEdit = true; } else if (pattUrlTimestamp.type3.test(val)) { eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type3, "")); isEdit = true; } if (isEdit) { val = eles[i].getAttribute(attr); } if (pattUrlTimestamp.type4.test(val)) { eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type4, "&")); } if (pattUrlTimestamp.type5.test(val)) { eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type5, "")); } } } var timeoutList = []; var intervalList = []; function setTimeoutCustom(func, tm, params) { var id = setTimeout(func, tm, params); timeoutList.push(id); return id; } function clearTimeoutAll() { for (var i = 0; i < timeoutList.length; i++) { clearTimeout(timeoutList[i]); } } function setIntervalCustom(func, tm, params) { var id = setInterval(func, tm, params); intervalList.push(id); return id; } function clearIntervalAll() { for (var i = 0; i < intervalList.length; i++) { clearInterval(intervalList[i]); } } function main() { var perfStart = 0; if (performance && performance.now) { perfStart = performance.now(); } var url = document.documentURI; var lang = getCookie("Language"); var userId = ""; var userName = ""; if (document.body) { document.body.classList.add("stsh"); } else { setTimeoutCustom(function() { if (document.body) { document.body.classList.add("stsh"); } }, timingInit.initNameSpace); } // Auto refresh when error { var h1 = document.querySelector("#leftAreaContainer > h1, body > h1"); if (h1) { var text = h1.textContent.trim(); if (text === "Steam Translation Server - Maintenance Warning" || text === "Forbidden") { console.log("stsh: refresh"); setTimeoutCustom(reload, timingInit.refreshError); return; } } } // Clean links { setTimeoutCustom(function() { var eles = document.querySelectorAll("a, form[action], input"); cleanUrlTimestamp(eles); }, timingInit.cleanLinks); } // Fix STS URL paths { var arrQuery = ["img"]; var arrAttr = ["src"]; for (var j = 0; j < arrQuery.length; j++) { var eles = document.querySelectorAll(arrQuery[j]); for (var i = 0; i < eles.length; i++) { var attr = eles[i].getAttribute(arrAttr[j]); if (attr) { var attrNew = attr.replace(/<\?=BASE_URL_CURRENT\?>/g, "/"); if (attrNew !== attr) { console.log("STS URL path is missing: " + eles[i].outerHTML); eles[i].setAttribute(arrAttr[j], attrNew); } } } } } // Set current user { userId = GM_getValue("user", ""); userName = GM_getValue("name", ""); if (url.indexOf("/home.php") > -1) { var eleUser = document.querySelector("#leftAreaContainer > b > a[href^='user_activity.php?user=']"); if (eleUser) { var user = getQueryByName("user", eleUser.href); if (user && userId !== user) { userId = user; GM_setValue("user", userId); } var name = eleUser.textContent.trim(); if (name && userName !== name) { userName = name; GM_setValue("name", userName); } } } } var eleLogout = document.querySelector("#logout"); if (eleLogout) { var logoutHtml = ' \ My Profile\ \ '; logoutHtml = logoutHtml .replace("%PROFILE%", "/user_activity.php" + (userId ? "?user=" + userId : "")) .replace("%NAME%", userName); eleLogout.innerHTML = logoutHtml; // Special event button { if (isRally()) { var divSpecial = document.createElement("div"); divSpecial.id = "stsh_specialEvent"; divSpecial.innerHTML = ' \ Year-End Rally \ '; eleLogout.parentElement.appendChild(divSpecial); } } } // Declare functions var removeStsHtmlTags = null; var displayHtmlTags = null; { removeStsHtmlTags = function(ele, isRemovedBrowserGenerated) { isRemovedBrowserGenerated = (typeof isRemovedBrowserGenerated === "undefined") ? true : !!isRemovedBrowserGenerated; var html = ""; if (ele) { html = (typeof ele.dataset.stshHtml === "undefined") ? trimTab(ele.innerHTML) : ele.dataset.stshHtml; if (ele.classList.contains("stsh_text_org")) { html = html.replace(/(.*?)<\/span>/ig, "$1") .replace(/(.*?)<\/span>/ig, "$1") .replace(/(.+?)<\/font>/ig, "$1") .replace(/(.+?)<\/font>/ig, "$1"); } else if (ele.classList.contains("stsh_text_trn")) { html = html.replace(/(.*?)<\/span>/ig, "$1") .replace(/(.*?)<\/span>/ig, "$1") .replace(/(.+?)<\/font>/ig, "$1"); } else if (ele.classList.contains("suggestion_text")) { html = html.replace(/(.*?)<\/span>/ig, "$1") .replace(/(.+?)<\/font>/ig, "$1"); } if (isRemovedBrowserGenerated) { // Remove browser generated attributes and ending tags // Regex .+? is "reluctant" that means "as few characters as it can" html = html.replace(/="">/g, ">") .replace(/([^\t])\t\t\t\t<\/[^\t ]+>$/, "$1") .replace(/