mirror of
https://github.com/GAM-team/GAM.git
synced 2025-07-10 14:43:34 +00:00
GAM 5.09
This commit is contained in:
@ -210,8 +210,8 @@ script:
|
|||||||
- if [ "$e2e" = true ]; then $gam print cros allfields nolists; fi
|
- if [ "$e2e" = true ]; then $gam print cros allfields nolists; fi
|
||||||
- if [ "$e2e" = true ]; then $gam report usageparameters customer; fi
|
- if [ "$e2e" = true ]; then $gam report usageparameters customer; fi
|
||||||
- if [ "$e2e" = true ]; then $gam report usage customer parameters gmail:num_emails_sent,accounts:num_1day_logins; fi
|
- if [ "$e2e" = true ]; then $gam report usage customer parameters gmail:num_emails_sent,accounts:num_1day_logins; fi
|
||||||
- if [ "$e2e" = true ]; then $gam report customer date -5d todrive; fi
|
- if [ "$e2e" = true ]; then $gam report customer todrive; fi
|
||||||
- if [ "$e2e" = true ]; then $gam report users date -5d fields accounts:is_less_secure_apps_access_allowed,gmail:last_imap_time,gmail:last_pop_time filters "accounts:last_login_time>2019-01-01T00:00:00.000Z" todrive; fi
|
- if [ "$e2e" = true ]; then $gam report users fields accounts:is_less_secure_apps_access_allowed,gmail:last_imap_time,gmail:last_pop_time filters "accounts:last_login_time>2019-01-01T00:00:00.000Z" todrive; fi
|
||||||
- if [ "$e2e" = true ]; then $gam report admin start -3d todrive; fi
|
- if [ "$e2e" = true ]; then $gam report admin start -3d todrive; fi
|
||||||
- if ([ "$e2e" = true ] && [[ "$TRAVIS_JOB_NAME" != *"Testing" ]]); then
|
- if ([ "$e2e" = true ] && [[ "$TRAVIS_JOB_NAME" != *"Testing" ]]); then
|
||||||
for gamfile in gam-$GAMVERSION-*; do
|
for gamfile in gam-$GAMVERSION-*; do
|
||||||
|
@ -602,7 +602,7 @@ def doGAMCheckForUpdates(forceCheck=False):
|
|||||||
controlflow.system_error_exit(
|
controlflow.system_error_exit(
|
||||||
4, 'GAM Latest Version information not available')
|
4, 'GAM Latest Version information not available')
|
||||||
|
|
||||||
current_version = gam_version
|
current_version = GAM_VERSION
|
||||||
now_time = int(time.time())
|
now_time = int(time.time())
|
||||||
if forceCheck:
|
if forceCheck:
|
||||||
check_url = GAM_ALL_RELEASES # includes pre-releases
|
check_url = GAM_ALL_RELEASES # includes pre-releases
|
||||||
@ -709,15 +709,15 @@ def doGAMVersion(checkForArgs=True):
|
|||||||
else:
|
else:
|
||||||
controlflow.invalid_argument_exit(sys.argv[i], 'gam version')
|
controlflow.invalid_argument_exit(sys.argv[i], 'gam version')
|
||||||
if simple:
|
if simple:
|
||||||
sys.stdout.write(gam_version)
|
sys.stdout.write(GAM_VERSION)
|
||||||
return
|
return
|
||||||
pyversion = platform.python_version()
|
pyversion = platform.python_version()
|
||||||
cpu_bits = struct.calcsize('P') * 8
|
cpu_bits = struct.calcsize('P') * 8
|
||||||
api_client_ver = pkg_resources.get_distribution(
|
api_client_ver = pkg_resources.get_distribution(
|
||||||
'google-api-python-client').version
|
'google-api-python-client').version
|
||||||
print(
|
print(
|
||||||
(f'GAM {gam_version} - {GAM_URL} - {GM_Globals[GM_GAM_TYPE]}\n'
|
(f'GAM {GAM_VERSION} - {GAM_URL} - {GM_Globals[GM_GAM_TYPE]}\n'
|
||||||
f'{gam_author}\n'
|
f'{GAM_AUTHOR}\n'
|
||||||
f'Python {pyversion} {cpu_bits}-bit {sys.version_info.releaselevel}\n'
|
f'Python {pyversion} {cpu_bits}-bit {sys.version_info.releaselevel}\n'
|
||||||
f'google-api-python-client {api_client_ver}\n'
|
f'google-api-python-client {api_client_ver}\n'
|
||||||
f'{getOSPlatform()} {platform.machine()}\n'
|
f'{getOSPlatform()} {platform.machine()}\n'
|
||||||
@ -3296,7 +3296,7 @@ def doPrinterRegister():
|
|||||||
'uuid':
|
'uuid':
|
||||||
_getValueFromOAuth('sub'),
|
_getValueFromOAuth('sub'),
|
||||||
'manufacturer':
|
'manufacturer':
|
||||||
gam_author,
|
GAM_AUTHOR,
|
||||||
'model':
|
'model':
|
||||||
'cp1',
|
'cp1',
|
||||||
'gcp_version':
|
'gcp_version':
|
||||||
@ -3308,7 +3308,7 @@ def doPrinterRegister():
|
|||||||
'update_url':
|
'update_url':
|
||||||
GAM_RELEASES,
|
GAM_RELEASES,
|
||||||
'firmware':
|
'firmware':
|
||||||
gam_version,
|
GAM_VERSION,
|
||||||
'semantic_state': {
|
'semantic_state': {
|
||||||
'version': '1.0',
|
'version': '1.0',
|
||||||
'printer': {
|
'printer': {
|
||||||
@ -8609,9 +8609,10 @@ def doCreateOrRotateServiceAccountKeys(iam=None,
|
|||||||
name, local_key_size)
|
name, local_key_size)
|
||||||
print(' Uploading new public certificate to Google...')
|
print(' Uploading new public certificate to Google...')
|
||||||
max_retries = 10
|
max_retries = 10
|
||||||
for i in range(1, max_retries+1):
|
for i in range(1, max_retries + 1):
|
||||||
try:
|
try:
|
||||||
result = gapi.call(iam.projects().serviceAccounts().keys(),
|
result = gapi.call(
|
||||||
|
iam.projects().serviceAccounts().keys(),
|
||||||
'upload',
|
'upload',
|
||||||
throw_reasons=[gapi_errors.ErrorReason.NOT_FOUND],
|
throw_reasons=[gapi_errors.ErrorReason.NOT_FOUND],
|
||||||
name=name,
|
name=name,
|
||||||
@ -8620,9 +8621,11 @@ def doCreateOrRotateServiceAccountKeys(iam=None,
|
|||||||
except gapi_errors.GapiNotFoundError as e:
|
except gapi_errors.GapiNotFoundError as e:
|
||||||
if i == max_retries:
|
if i == max_retries:
|
||||||
raise e
|
raise e
|
||||||
sleep_time = i*5
|
sleep_time = i * 5
|
||||||
if i > 3:
|
if i > 3:
|
||||||
print(f'Waiting for Service Account creation to complete. Sleeping {sleep_time} seconds\n')
|
print(
|
||||||
|
f'Waiting for Service Account creation to complete. Sleeping {sleep_time} seconds\n'
|
||||||
|
)
|
||||||
time.sleep(sleep_time)
|
time.sleep(sleep_time)
|
||||||
private_key_id = result['name'].rsplit('/', 1)[-1]
|
private_key_id = result['name'].rsplit('/', 1)[-1]
|
||||||
oauth2service_data = _formatOAuth2ServiceData(project_id, client_email,
|
oauth2service_data = _formatOAuth2ServiceData(project_id, client_email,
|
||||||
@ -9894,8 +9897,8 @@ def doWhatIs():
|
|||||||
],
|
],
|
||||||
userKey=email,
|
userKey=email,
|
||||||
fields='id,primaryEmail')
|
fields='id,primaryEmail')
|
||||||
if (user_or_alias['primaryEmail'].lower() == email) or (
|
if (user_or_alias['primaryEmail'].lower()
|
||||||
user_or_alias['id'] == email):
|
== email) or (user_or_alias['id'] == email):
|
||||||
sys.stderr.write(f'{email} is a user\n\n')
|
sys.stderr.write(f'{email} is a user\n\n')
|
||||||
doGetUserInfo(user_email=email)
|
doGetUserInfo(user_email=email)
|
||||||
return
|
return
|
||||||
@ -12915,9 +12918,8 @@ def getUsersToModify(entity_type=None,
|
|||||||
query=query)
|
query=query)
|
||||||
for member in members:
|
for member in members:
|
||||||
email = member['primaryEmail']
|
email = member['primaryEmail']
|
||||||
if (checkSuspended is None or
|
if (checkSuspended is None or checkSuspended
|
||||||
checkSuspended == member['suspended']
|
== member['suspended']) and email not in usersSet:
|
||||||
) and email not in usersSet:
|
|
||||||
usersSet.add(email)
|
usersSet.add(email)
|
||||||
users.append(email)
|
users.append(email)
|
||||||
if not silent:
|
if not silent:
|
||||||
|
153
src/gam/var.py
153
src/gam/var.py
@ -1,3 +1,4 @@
|
|||||||
|
"""Variables common across modules"""
|
||||||
import os
|
import os
|
||||||
import ssl
|
import ssl
|
||||||
import string
|
import string
|
||||||
@ -5,13 +6,13 @@ import sys
|
|||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
|
|
||||||
gam_author = 'Jay Lee <jay0lee@gmail.com>'
|
GAM_AUTHOR = 'Jay Lee <jay0lee@gmail.com>'
|
||||||
gam_version = '5.08'
|
GAM_VERSION = '5.09'
|
||||||
gam_license = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
GAM_LICENSE = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||||
|
|
||||||
GAM_URL = 'https://git.io/gam'
|
GAM_URL = 'https://git.io/gam'
|
||||||
GAM_INFO = (
|
GAM_INFO = (
|
||||||
f'GAM {gam_version} - {GAM_URL} / {gam_author} / '
|
f'GAM {GAM_VERSION} - {GAM_URL} / {GAM_AUTHOR} / '
|
||||||
f'Python {platform.python_version()} {sys.version_info.releaselevel} / '
|
f'Python {platform.python_version()} {sys.version_info.releaselevel} / '
|
||||||
f'{platform.platform()} {platform.machine()}')
|
f'{platform.platform()} {platform.machine()}')
|
||||||
|
|
||||||
@ -930,7 +931,12 @@ CROS_DISK_VOLUME_REPORTS_ARGUMENTS = [
|
|||||||
CROS_SYSTEM_RAM_FREE_REPORTS_ARGUMENTS = [
|
CROS_SYSTEM_RAM_FREE_REPORTS_ARGUMENTS = [
|
||||||
'systemramfreereports',
|
'systemramfreereports',
|
||||||
]
|
]
|
||||||
CROS_LISTS_ARGUMENTS = CROS_ACTIVE_TIME_RANGES_ARGUMENTS + CROS_RECENT_USERS_ARGUMENTS + CROS_DEVICE_FILES_ARGUMENTS + CROS_CPU_STATUS_REPORTS_ARGUMENTS + CROS_DISK_VOLUME_REPORTS_ARGUMENTS + CROS_SYSTEM_RAM_FREE_REPORTS_ARGUMENTS
|
CROS_LISTS_ARGUMENTS = CROS_ACTIVE_TIME_RANGES_ARGUMENTS + \
|
||||||
|
CROS_RECENT_USERS_ARGUMENTS + \
|
||||||
|
CROS_DEVICE_FILES_ARGUMENTS + \
|
||||||
|
CROS_CPU_STATUS_REPORTS_ARGUMENTS + \
|
||||||
|
CROS_DISK_VOLUME_REPORTS_ARGUMENTS + \
|
||||||
|
CROS_SYSTEM_RAM_FREE_REPORTS_ARGUMENTS
|
||||||
CROS_START_ARGUMENTS = ['start', 'startdate', 'oldestdate']
|
CROS_START_ARGUMENTS = ['start', 'startdate', 'oldestdate']
|
||||||
CROS_END_ARGUMENTS = ['end', 'enddate']
|
CROS_END_ARGUMENTS = ['end', 'enddate']
|
||||||
|
|
||||||
@ -1097,7 +1103,8 @@ GM_Globals = {
|
|||||||
#
|
#
|
||||||
# Global variables defined by environment variables/signal files
|
# Global variables defined by environment variables/signal files
|
||||||
#
|
#
|
||||||
# Automatically generate gam batch command if number of users specified in gam users xxx command exceeds this number
|
# Automatically generate gam batch command if number of users specified in gam
|
||||||
|
# users xxx command exceeds this number
|
||||||
# Default: 0, don't automatically generate gam batch commands
|
# Default: 0, don't automatically generate gam batch commands
|
||||||
GC_AUTO_BATCH_MIN = 'auto_batch_min'
|
GC_AUTO_BATCH_MIN = 'auto_batch_min'
|
||||||
# When processing items in batches, how many should be processed in each batch
|
# When processing items in batches, how many should be processed in each batch
|
||||||
@ -1110,20 +1117,24 @@ GC_CACHE_DISCOVERY_ONLY = 'cache_discovery_only'
|
|||||||
GC_CHARSET = 'charset'
|
GC_CHARSET = 'charset'
|
||||||
# Path to client_secrets.json
|
# Path to client_secrets.json
|
||||||
GC_CLIENT_SECRETS_JSON = 'client_secrets_json'
|
GC_CLIENT_SECRETS_JSON = 'client_secrets_json'
|
||||||
# GAM config directory containing client_secrets.json, oauth2.txt, oauth2service.json, extra_args.txt
|
# GAM config directory containing client_secrets.json, oauth2.txt,
|
||||||
|
# oauth2service.json, extra_args.txt
|
||||||
GC_CONFIG_DIR = 'config_dir'
|
GC_CONFIG_DIR = 'config_dir'
|
||||||
# custmerId from gam.cfg or retrieved from Google
|
# custmerId from gam.cfg or retrieved from Google
|
||||||
GC_CUSTOMER_ID = 'customer_id'
|
GC_CUSTOMER_ID = 'customer_id'
|
||||||
# If debug_level > 0: extra_args[u'prettyPrint'] = True, httplib2.debuglevel = gam_debug_level, appsObj.debug = True
|
# If debug_level > 0: extra_args[u'prettyPrint'] = True,
|
||||||
|
# httplib2.debuglevel = gam_debug_level, appsObj.debug = True
|
||||||
GC_DEBUG_LEVEL = 'debug_level'
|
GC_DEBUG_LEVEL = 'debug_level'
|
||||||
# ID Token decoded from OAuth 2.0 refresh token response. Includes hd (domain) and email of authorized user
|
# ID Token decoded from OAuth 2.0 refresh token response. Includes hd (domain)
|
||||||
|
# and email of authorized user
|
||||||
GC_DECODED_ID_TOKEN = 'decoded_id_token'
|
GC_DECODED_ID_TOKEN = 'decoded_id_token'
|
||||||
# Domain obtained from gam.cfg or oauth2.txt
|
# Domain obtained from gam.cfg or oauth2.txt
|
||||||
GC_DOMAIN = 'domain'
|
GC_DOMAIN = 'domain'
|
||||||
# Google Drive download directory
|
# Google Drive download directory
|
||||||
GC_DRIVE_DIR = 'drive_dir'
|
GC_DRIVE_DIR = 'drive_dir'
|
||||||
# If no_browser is False, writeCSVfile won't open a browser when todrive is set
|
# If no_browser is False, writeCSVfile won't open a browser when todrive is set
|
||||||
# and doRequestOAuth prints a link and waits for the verification code when oauth2.txt is being created
|
# and doRequestOAuth prints a link and waits for the verification code when
|
||||||
|
# oauth2.txt is being created
|
||||||
GC_NO_BROWSER = 'no_browser'
|
GC_NO_BROWSER = 'no_browser'
|
||||||
# oauth_browser forces usage of web server OAuth flow that proved problematic.
|
# oauth_browser forces usage of web server OAuth flow that proved problematic.
|
||||||
GC_OAUTH_BROWSER = 'oauth_browser'
|
GC_OAUTH_BROWSER = 'oauth_browser'
|
||||||
@ -1158,7 +1169,7 @@ GC_TLS_MAX_VERSION = 'tls_max_ver'
|
|||||||
# Path to certificate authority file for validating TLS hosts
|
# Path to certificate authority file for validating TLS hosts
|
||||||
GC_CA_FILE = 'ca_file'
|
GC_CA_FILE = 'ca_file'
|
||||||
|
|
||||||
tls_min = 'TLSv1_2' if hasattr(ssl.SSLContext(), 'minimum_version') else None
|
TLS_MIN = 'TLSv1_2' if hasattr(ssl.SSLContext(), 'minimum_version') else None
|
||||||
GC_Defaults = {
|
GC_Defaults = {
|
||||||
GC_AUTO_BATCH_MIN: 0,
|
GC_AUTO_BATCH_MIN: 0,
|
||||||
GC_BATCH_SIZE: 50,
|
GC_BATCH_SIZE: 50,
|
||||||
@ -1186,7 +1197,7 @@ GC_Defaults = {
|
|||||||
GC_CSV_HEADER_FILTER: '',
|
GC_CSV_HEADER_FILTER: '',
|
||||||
GC_CSV_HEADER_DROP_FILTER: '',
|
GC_CSV_HEADER_DROP_FILTER: '',
|
||||||
GC_CSV_ROW_FILTER: '',
|
GC_CSV_ROW_FILTER: '',
|
||||||
GC_TLS_MIN_VERSION: tls_min,
|
GC_TLS_MIN_VERSION: TLS_MIN,
|
||||||
GC_TLS_MAX_VERSION: None,
|
GC_TLS_MAX_VERSION: None,
|
||||||
GC_CA_FILE: None,
|
GC_CA_FILE: None,
|
||||||
}
|
}
|
||||||
@ -1321,20 +1332,52 @@ CLEAR_NONE_ARGUMENT = [
|
|||||||
'none',
|
'none',
|
||||||
]
|
]
|
||||||
#
|
#
|
||||||
MESSAGE_API_ACCESS_CONFIG = 'API access is configured in your Control Panel under: Security-Show more-Advanced settings-Manage API client access'
|
MESSAGE_API_ACCESS_CONFIG = 'API access is configured in your Control Panel' \
|
||||||
MESSAGE_API_ACCESS_DENIED = 'API access Denied.\n\nPlease make sure the Client ID: {0} is authorized for the API Scope(s): {1}'
|
' under: Security-Show more-Advanced' \
|
||||||
MESSAGE_GAM_EXITING_FOR_UPDATE = 'GAM is now exiting so that you can overwrite this old version with the latest release'
|
' settings-Manage API client access'
|
||||||
MESSAGE_GAM_OUT_OF_MEMORY = 'GAM has run out of memory. If this is a large G Suite instance, you should use a 64-bit version of GAM on Windows or a 64-bit version of Python on other systems.'
|
MESSAGE_API_ACCESS_DENIED = 'API access Denied.\n\nPlease make sure the Client' \
|
||||||
MESSAGE_HEADER_NOT_FOUND_IN_CSV_HEADERS = 'Header "{0}" not found in CSV headers of "{1}".'
|
' ID: {0} is authorized for the API Scope(s): {1}'
|
||||||
MESSAGE_HIT_CONTROL_C_TO_UPDATE = '\n\nHit CTRL+C to visit the GAM website and download the latest release or wait 15 seconds continue with this boring old version. GAM won\'t bother you with this announcement for 1 week or you can create a file named noupdatecheck.txt in the same location as gam.py or gam.exe and GAM won\'t ever check for updates.'
|
MESSAGE_GAM_EXITING_FOR_UPDATE = 'GAM is now exiting so that you can' \
|
||||||
|
' overwrite this old version with the' \
|
||||||
|
' latest release'
|
||||||
|
MESSAGE_GAM_OUT_OF_MEMORY = 'GAM has run out of memory. If this is a large' \
|
||||||
|
' G Suite instance, you should use a 64-bit' \
|
||||||
|
' version of GAM on Windows or a 64-bit version' \
|
||||||
|
' of Python on other systems.'
|
||||||
|
MESSAGE_HEADER_NOT_FOUND_IN_CSV_HEADERS = 'Header "{0}" not found in CSV' \
|
||||||
|
' headers of "{1}".'
|
||||||
|
MESSAGE_HIT_CONTROL_C_TO_UPDATE = '\n\nHit CTRL+C to visit the GAM website' \
|
||||||
|
' and download the latest release or wait' \
|
||||||
|
' 15 seconds continue with this boring old' \
|
||||||
|
' version. GAM won\'t bother you with this ' \
|
||||||
|
' announcement for 1 week or you can create' \
|
||||||
|
' a file named noupdatecheck.txt in the same' \
|
||||||
|
' location as gam.py or gam.exe and GAM' \
|
||||||
|
' won\'t ever check for updates.'
|
||||||
MESSAGE_INVALID_JSON = 'The file {0} has an invalid format.'
|
MESSAGE_INVALID_JSON = 'The file {0} has an invalid format.'
|
||||||
MESSAGE_NO_DISCOVERY_INFORMATION = 'No online discovery doc and {0} does not exist locally'
|
MESSAGE_NO_DISCOVERY_INFORMATION = 'No online discovery doc and {0} does not' \
|
||||||
MESSAGE_NO_TRANSFER_LACK_OF_DISK_SPACE = 'Cowardly refusing to perform migration due to lack of target drive space. Source size: {0}mb Target Free: {1}mb'
|
' exist locally'
|
||||||
MESSAGE_RESULTS_TOO_LARGE_FOR_GOOGLE_SPREADSHEET = 'Results are too large for Google Spreadsheets. Uploading as a regular CSV file.'
|
MESSAGE_NO_TRANSFER_LACK_OF_DISK_SPACE = 'Cowardly refusing to perform' \
|
||||||
MESSAGE_SERVICE_NOT_APPLICABLE = 'Service not applicable for this address: {0}. Please make sure service is enabled for user and run\n\ngam user <user> check serviceaccount\n\nfor further instructions'
|
' migration due to lack of target' \
|
||||||
MESSAGE_INSTRUCTIONS_OAUTH2SERVICE_JSON = 'Please run\n\ngam create project\ngam user <user> check serviceaccount\n\nto create and configure a service account.'
|
' drive space. Source size: {0}mb' \
|
||||||
MESSAGE_UPDATE_GAM_TO_64BIT = "You're running a 32-bit version of GAM on a 64-bit version of Windows, upgrade to a windows-x86_64 version of GAM"
|
' Target Free: {1}mb'
|
||||||
MESSAGE_YOUR_SYSTEM_TIME_DIFFERS_FROM_GOOGLE_BY = 'Your system time differs from %s by %s'
|
MESSAGE_RESULTS_TOO_LARGE_FOR_GOOGLE_SPREADSHEET = 'Results are too large for' \
|
||||||
|
' Google Spreadsheets.' \
|
||||||
|
' Uploading as a regular' \
|
||||||
|
' CSV file.'
|
||||||
|
MESSAGE_SERVICE_NOT_APPLICABLE = 'Service not applicable for this address:' \
|
||||||
|
' {0}. Please make sure service is enabled' \
|
||||||
|
' for user and run\n\ngam user <user> check' \
|
||||||
|
' serviceaccount\n\nfor further instructions'
|
||||||
|
MESSAGE_INSTRUCTIONS_OAUTH2SERVICE_JSON = 'Please run\n\ngam create project\n' \
|
||||||
|
'gam user <user> check ' \
|
||||||
|
'serviceaccount\n\nto create and' \
|
||||||
|
' configure a service account.'
|
||||||
|
MESSAGE_UPDATE_GAM_TO_64BIT = 'You\'re running a 32-bit version of GAM on a' \
|
||||||
|
' 64-bit version of Windows, upgrade to a' \
|
||||||
|
' windows-x86_64 version of GAM'
|
||||||
|
MESSAGE_YOUR_SYSTEM_TIME_DIFFERS_FROM_GOOGLE_BY = 'Your system time differs' \
|
||||||
|
' from %s by %s'
|
||||||
|
|
||||||
USER_ADDRESS_TYPES = ['home', 'work', 'other']
|
USER_ADDRESS_TYPES = ['home', 'work', 'other']
|
||||||
USER_EMAIL_TYPES = ['home', 'work', 'other']
|
USER_EMAIL_TYPES = ['home', 'work', 'other']
|
||||||
@ -1587,167 +1630,151 @@ LANGUAGE_CODES_MAP = {
|
|||||||
'ak': 'ak',
|
'ak': 'ak',
|
||||||
'am': 'am',
|
'am': 'am',
|
||||||
'ar': 'ar',
|
'ar': 'ar',
|
||||||
'az': 'az', #Luo, Afrikaans, Irish, Akan, Amharic, Arabica, Azerbaijani
|
'az': 'az',
|
||||||
'be': 'be',
|
'be': 'be',
|
||||||
'bem': 'bem',
|
'bem': 'bem',
|
||||||
'bg': 'bg',
|
'bg': 'bg',
|
||||||
'bn': 'bn',
|
'bn': 'bn',
|
||||||
'br': 'br',
|
'br': 'br',
|
||||||
'bs': 'bs',
|
'bs': 'bs',
|
||||||
'ca':
|
'ca': 'ca',
|
||||||
'ca', #Belarusian, Bemba, Bulgarian, Bengali, Breton, Bosnian, Catalan
|
|
||||||
'chr': 'chr',
|
'chr': 'chr',
|
||||||
'ckb': 'ckb',
|
'ckb': 'ckb',
|
||||||
'co': 'co',
|
'co': 'co',
|
||||||
'crs': 'crs',
|
'crs': 'crs',
|
||||||
'cs': 'cs',
|
'cs': 'cs',
|
||||||
'cy': 'cy',
|
'cy': 'cy',
|
||||||
'da':
|
'da': 'da',
|
||||||
'da', #Cherokee, Kurdish (Sorani), Corsican, Seychellois Creole, Czech, Welsh, Danish
|
|
||||||
'de': 'de',
|
'de': 'de',
|
||||||
'ee': 'ee',
|
'ee': 'ee',
|
||||||
'el': 'el',
|
'el': 'el',
|
||||||
'en': 'en',
|
'en': 'en',
|
||||||
'en-gb': 'en-GB',
|
'en-gb': 'en-GB',
|
||||||
'en-us': 'en-US',
|
'en-us': 'en-US',
|
||||||
'eo':
|
'eo': 'eo',
|
||||||
'eo', #German, Ewe, Greek, English, English (UK), English (US), Esperanto
|
|
||||||
'es': 'es',
|
'es': 'es',
|
||||||
'es-419': 'es-419',
|
'es-419': 'es-419',
|
||||||
'et': 'et',
|
'et': 'et',
|
||||||
'eu': 'eu',
|
'eu': 'eu',
|
||||||
'fa': 'fa',
|
'fa': 'fa',
|
||||||
'fi': 'fi',
|
'fi': 'fi',
|
||||||
'fo':
|
'fo': 'fo',
|
||||||
'fo', #Spanish, Spanish (Latin American), Estonian, Basque, Persian, Finnish, Faroese
|
|
||||||
'fr': 'fr',
|
'fr': 'fr',
|
||||||
'fr-ca': 'fr-ca',
|
'fr-ca': 'fr-ca',
|
||||||
'fy': 'fy',
|
'fy': 'fy',
|
||||||
'ga': 'ga',
|
'ga': 'ga',
|
||||||
'gaa': 'gaa',
|
'gaa': 'gaa',
|
||||||
'gd': 'gd',
|
'gd': 'gd',
|
||||||
'gl':
|
'gl': 'gl',
|
||||||
'gl', #French, French (Canada), Frisian, Irish, Ga, Scots Gaelic, Galician
|
|
||||||
'gn': 'gn',
|
'gn': 'gn',
|
||||||
'gu': 'gu',
|
'gu': 'gu',
|
||||||
'ha': 'ha',
|
'ha': 'ha',
|
||||||
'haw': 'haw',
|
'haw': 'haw',
|
||||||
'he': 'he',
|
'he': 'he',
|
||||||
'hi': 'hi',
|
'hi': 'hi',
|
||||||
'hr': 'hr', #Guarani, Gujarati, Hausa, Hawaiian, Hebrew, Hindi, Croatian
|
'hr': 'hr',
|
||||||
'ht': 'ht',
|
'ht': 'ht',
|
||||||
'hu': 'hu',
|
'hu': 'hu',
|
||||||
'hy': 'hy',
|
'hy': 'hy',
|
||||||
'ia': 'ia',
|
'ia': 'ia',
|
||||||
'id': 'id',
|
'id': 'id',
|
||||||
'ig': 'ig',
|
'ig': 'ig',
|
||||||
'in':
|
'in': 'in',
|
||||||
'in', #Haitian Creole, Hungarian, Armenian, Interlingua, Indonesian, Igbo, in
|
|
||||||
'is': 'is',
|
'is': 'is',
|
||||||
'it': 'it',
|
'it': 'it',
|
||||||
'iw': 'iw',
|
'iw': 'iw',
|
||||||
'ja': 'ja',
|
'ja': 'ja',
|
||||||
'jw': 'jw',
|
'jw': 'jw',
|
||||||
'ka': 'ka',
|
'ka': 'ka',
|
||||||
'kg':
|
'kg': 'kg',
|
||||||
'kg', #Icelandic, Italian, Hebrew, Japanese, Javanese, Georgian, Kongo
|
|
||||||
'kk': 'kk',
|
'kk': 'kk',
|
||||||
'km': 'km',
|
'km': 'km',
|
||||||
'kn': 'kn',
|
'kn': 'kn',
|
||||||
'ko': 'ko',
|
'ko': 'ko',
|
||||||
'kri': 'kri',
|
'kri': 'kri',
|
||||||
'ku': 'ku',
|
'ku': 'ku',
|
||||||
'ky':
|
'ky': 'ky',
|
||||||
'ky', #Kazakh, Khmer, Kannada, Korean, Krio (Sierra Leone), Kurdish, Kyrgyz
|
|
||||||
'la': 'la',
|
'la': 'la',
|
||||||
'lg': 'lg',
|
'lg': 'lg',
|
||||||
'ln': 'ln',
|
'ln': 'ln',
|
||||||
'lo': 'lo',
|
'lo': 'lo',
|
||||||
'loz': 'loz',
|
'loz': 'loz',
|
||||||
'lt': 'lt',
|
'lt': 'lt',
|
||||||
'lua':
|
'lua': 'lua',
|
||||||
'lua', #Latin, Luganda, Lingala, Laothian, Lozi, Lithuanian, Tshiluba
|
|
||||||
'lv': 'lv',
|
'lv': 'lv',
|
||||||
'mfe': 'mfe',
|
'mfe': 'mfe',
|
||||||
'mg': 'mg',
|
'mg': 'mg',
|
||||||
'mi': 'mi',
|
'mi': 'mi',
|
||||||
'mk': 'mk',
|
'mk': 'mk',
|
||||||
'ml': 'ml',
|
'ml': 'ml',
|
||||||
'mn':
|
'mn': 'mn',
|
||||||
'mn', #Latvian, Mauritian Creole, Malagasy, Maori, Macedonian, Malayalam, Mongolian
|
|
||||||
'mo': 'mo',
|
'mo': 'mo',
|
||||||
'mr': 'mr',
|
'mr': 'mr',
|
||||||
'ms': 'ms',
|
'ms': 'ms',
|
||||||
'mt': 'mt',
|
'mt': 'mt',
|
||||||
'my': 'my',
|
'my': 'my',
|
||||||
'ne': 'ne',
|
'ne': 'ne',
|
||||||
'nl': 'nl', #Moldavian, Marathi, Malay, Maltese, Burmese, Nepali, Dutch
|
'nl': 'nl',
|
||||||
'nn': 'nn',
|
'nn': 'nn',
|
||||||
'no': 'no',
|
'no': 'no',
|
||||||
'nso': 'nso',
|
'nso': 'nso',
|
||||||
'ny': 'ny',
|
'ny': 'ny',
|
||||||
'nyn': 'nyn',
|
'nyn': 'nyn',
|
||||||
'oc': 'oc',
|
'oc': 'oc',
|
||||||
'om':
|
'om': 'om',
|
||||||
'om', #Norwegian (Nynorsk), Norwegian, Northern Sotho, Chichewa, Runyakitara, Occitan, Oromo
|
|
||||||
'or': 'or',
|
'or': 'or',
|
||||||
'pa': 'pa',
|
'pa': 'pa',
|
||||||
'pcm': 'pcm',
|
'pcm': 'pcm',
|
||||||
'pl': 'pl',
|
'pl': 'pl',
|
||||||
'ps': 'ps',
|
'ps': 'ps',
|
||||||
'pt-br': 'pt-BR',
|
'pt-br': 'pt-BR',
|
||||||
'pt-pt':
|
'pt-pt': 'pt-PT',
|
||||||
'pt-PT', #Oriya, Punjabi, Nigerian Pidgin, Polish, Pashto, Portuguese (Brazil), Portuguese (Portugal)
|
|
||||||
'qu': 'qu',
|
'qu': 'qu',
|
||||||
'rm': 'rm',
|
'rm': 'rm',
|
||||||
'rn': 'rn',
|
'rn': 'rn',
|
||||||
'ro': 'ro',
|
'ro': 'ro',
|
||||||
'ru': 'ru',
|
'ru': 'ru',
|
||||||
'rw': 'rw',
|
'rw': 'rw',
|
||||||
'sd':
|
'sd': 'sd',
|
||||||
'sd', #Quechua, Romansh, Kirundi, Romanian, Russian, Kinyarwanda, Sindhi
|
|
||||||
'sh': 'sh',
|
'sh': 'sh',
|
||||||
'si': 'si',
|
'si': 'si',
|
||||||
'sk': 'sk',
|
'sk': 'sk',
|
||||||
'sl': 'sl',
|
'sl': 'sl',
|
||||||
'sn': 'sn',
|
'sn': 'sn',
|
||||||
'so': 'so',
|
'so': 'so',
|
||||||
'sq':
|
'sq': 'sq',
|
||||||
'sq', #Serbo-Croatian, Sinhalese, Slovak, Slovenian, Shona, Somali, Albanian
|
|
||||||
'sr': 'sr',
|
'sr': 'sr',
|
||||||
'sr-me': 'sr-ME',
|
'sr-me': 'sr-ME',
|
||||||
'st': 'st',
|
'st': 'st',
|
||||||
'su': 'su',
|
'su': 'su',
|
||||||
'sv': 'sv',
|
'sv': 'sv',
|
||||||
'sw': 'sw',
|
'sw': 'sw',
|
||||||
'ta':
|
'ta': 'ta',
|
||||||
'ta', #Serbian, Montenegrin, Sesotho, Sundanese, Swedish, Swahili, Tamil
|
|
||||||
'te': 'te',
|
'te': 'te',
|
||||||
'tg': 'tg',
|
'tg': 'tg',
|
||||||
'th': 'th',
|
'th': 'th',
|
||||||
'ti': 'ti',
|
'ti': 'ti',
|
||||||
'tk': 'tk',
|
'tk': 'tk',
|
||||||
'tl': 'tl',
|
'tl': 'tl',
|
||||||
'tn': 'tn', #Telugu, Tajik, Thai, Tigrinya, Turkmen, Tagalog, Setswana
|
'tn': 'tn',
|
||||||
'to': 'to',
|
'to': 'to',
|
||||||
'tr': 'tr',
|
'tr': 'tr',
|
||||||
'tt': 'tt',
|
'tt': 'tt',
|
||||||
'tum': 'tum',
|
'tum': 'tum',
|
||||||
'tw': 'tw',
|
'tw': 'tw',
|
||||||
'ug': 'ug',
|
'ug': 'ug',
|
||||||
'uk': 'uk', #Tonga, Turkish, Tatar, Tumbuka, Twi, Uighur, Ukrainian
|
'uk': 'uk',
|
||||||
'ur': 'ur',
|
'ur': 'ur',
|
||||||
'uz': 'uz',
|
'uz': 'uz',
|
||||||
'vi': 'vi',
|
'vi': 'vi',
|
||||||
'wo': 'wo',
|
'wo': 'wo',
|
||||||
'xh': 'xh',
|
'xh': 'xh',
|
||||||
'yi': 'yi',
|
'yi': 'yi',
|
||||||
'yo': 'yo', #Urdu, Uzbek, Vietnamese, Wolof, Xhosa, Yiddish, Yoruba
|
'yo': 'yo',
|
||||||
'zh-cn': 'zh-CN',
|
'zh-cn': 'zh-CN',
|
||||||
'zh-hk': 'zh-HK',
|
'zh-hk': 'zh-HK',
|
||||||
'zh-tw': 'zh-TW',
|
'zh-tw': 'zh-TW',
|
||||||
'zu':
|
'zu': 'zu',
|
||||||
'zu', #Chinese (Simplified), Chinese (Hong Kong/Traditional), Chinese (Taiwan/Traditional), Zulu
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# maxResults exception values for API list calls. Should only be listed if:
|
# maxResults exception values for API list calls. Should only be listed if:
|
||||||
|
Reference in New Issue
Block a user