diff --git a/po/zh_CN.po b/po/zh_CN.po
index e8d39db14d..82b2ced597 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -1,852 +1,1018 @@
 #
 # Copyright 2003-2022 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
 # This source code is licensed under the GNU Lesser General Public License
 # version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
 #
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: Pacemaker 2\n"
 "Report-Msgid-Bugs-To: developers@clusterlabs.org\n"
-"POT-Creation-Date: 2022-11-22 16:46+0800\n"
+"POT-Creation-Date: 2022-11-24 17:50+0800\n"
 "PO-Revision-Date: 2021-11-08 11:04+0800\n"
 "Last-Translator: Vivi <developers@clusterlabs.org>\n"
 "Language-Team: CHINESE <wangluwei@uniontech.org>\n"
 "Language: zh_CN\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
 #: daemons/controld/controld_control.c:530
 msgid "Pacemaker version on cluster node elected Designated Controller (DC)"
 msgstr "集群选定的控制器节点(DC)的 Pacemaker 版本"
 
 #: daemons/controld/controld_control.c:531
 msgid ""
 "Includes a hash which identifies the exact changeset the code was built "
 "from. Used for diagnostic purposes."
 msgstr "它包含一个标识所构建代码变更版本的哈希值,其可用于诊断。"
 
 #: daemons/controld/controld_control.c:536
 msgid "The messaging stack on which Pacemaker is currently running"
 msgstr "Pacemaker 正在使用的消息传输引擎"
 
 #: daemons/controld/controld_control.c:537
 msgid "Used for informational and diagnostic purposes."
 msgstr "用于提供信息和诊断。"
 
 #: daemons/controld/controld_control.c:541
 msgid "An arbitrary name for the cluster"
 msgstr "任意的集群名称"
 
 #: daemons/controld/controld_control.c:542
 msgid ""
 "This optional value is mostly for users' convenience as desired in "
 "administration, but may also be used in Pacemaker configuration rules via "
 "the #cluster-name node attribute, and by higher-level tools and resource "
 "agents."
 msgstr ""
 "该可选值主要是为了方便用户管理使用,也可以在pacemaker 配置规则中通过 "
 "#cluster-name 节点属性配置使用,也可以通过高级工具和资源代理使用。"
 
 #: daemons/controld/controld_control.c:550
 msgid "How long to wait for a response from other nodes during start-up"
 msgstr "启动过程中等待其他节点响应的时间"
 
 #: daemons/controld/controld_control.c:551
 msgid ""
 "The optimal value will depend on the speed and load of your network and the "
 "type of switches used."
 msgstr "其最佳值将取决于你的网络速度和负载以及所用交换机的类型。"
 
 #: daemons/controld/controld_control.c:556
 msgid ""
 "Zero disables polling, while positive values are an interval in "
 "seconds(unless other units are specified, for example \"5min\")"
 msgstr ""
 "设置为0将禁用轮询,设置为正数将是以秒为单位的时间间隔(除非使用了其他单位,比"
 "如\"5min\"表示5分钟)"
 
 #: daemons/controld/controld_control.c:559
 msgid ""
 "Polling interval to recheck cluster state and evaluate rules with date "
 "specifications"
 msgstr "重新检查集群状态并且评估具有日期规格的配置规则的轮询间隔"
 
 #: daemons/controld/controld_control.c:561
 msgid ""
 "Pacemaker is primarily event-driven, and looks ahead to know when to recheck "
 "cluster state for failure timeouts and most time-based rules. However, it "
 "will also recheck the cluster after this amount of inactivity, to evaluate "
 "rules with date specifications and serve as a fail-safe for certain types of "
 "scheduler bugs."
 msgstr ""
 "Pacemaker 主要是通过事件驱动的,并能预期重新检查集群状态以评估大多数基于时间"
 "的规则以及过期的错误。然而无论如何,在集群经过该时间间隔的不活动状态后,它还"
 "将重新检查集群,以评估具有日期规格的规则,并为某些类型的调度程序缺陷提供故障"
 "保护。"
 
 #: daemons/controld/controld_control.c:570
 msgid "Maximum amount of system load that should be used by cluster nodes"
 msgstr "集群节点应该使用的最大系统负载量"
 
 #: daemons/controld/controld_control.c:571
 msgid ""
 "The cluster will slow down its recovery process when the amount of system "
 "resources used (currently CPU) approaches this limit"
 msgstr "当使用的系统资源量(当前为CPU)接近此限制时,集群将减慢其恢复过程"
 
 #: daemons/controld/controld_control.c:577
 msgid ""
 "Maximum number of jobs that can be scheduled per node (defaults to 2x cores)"
 msgstr "每个节点可以调度的最大作业数(默认为2x内核数)"
 
 #: daemons/controld/controld_control.c:581
 msgid "How a cluster node should react if notified of its own fencing"
 msgstr "集群节点在收到针对自己的 fence 操作结果通知时应如何反应"
 
 #: daemons/controld/controld_control.c:582
 msgid ""
 "A cluster node may receive notification of its own fencing if fencing is "
 "misconfigured, or if fabric fencing is in use that doesn't cut cluster "
 "communication. Allowed values are \"stop\" to attempt to immediately stop "
 "Pacemaker and stay stopped, or \"panic\" to attempt to immediately reboot "
 "the local node, falling back to stop on failure."
 msgstr ""
 "如果有错误的 fence 配置,或者在使用 fabric fence 机制 (并不会切断集群通信),"
 "则集群节点可能会收到针对自己的 fence 结果通知。允许的值为 \"stop\" 尝试立即停"
 "止 pacemaker 并保持停用状态,或者 \"panic\" 尝试立即重新启动本地节点,并在失败"
 "时返回执行stop。"
 
 #: daemons/controld/controld_control.c:592
 msgid ""
 "Declare an election failed if it is not decided within this much time. If "
 "you need to adjust this value, it probably indicates the presence of a bug."
 msgstr ""
 "如果集群在本项设置时间内没有作出决定则宣布选举失败。如果您需要调整该值,这可"
 "能代表存在某些缺陷。"
 
 #: daemons/controld/controld_control.c:600
 msgid ""
 "Exit immediately if shutdown does not complete within this much time. If you "
 "need to adjust this value, it probably indicates the presence of a bug."
 msgstr ""
 "如果在这段时间内关机仍未完成,则立即退出。如果您需要调整该值,这可能代表存在"
 "某些缺陷。"
 
 #: daemons/controld/controld_control.c:608
 #: daemons/controld/controld_control.c:615
 msgid ""
 "If you need to adjust this value, it probably indicates the presence of a "
 "bug."
 msgstr "如果您需要调整该值,这可能代表存在某些缺陷。"
 
 #: daemons/controld/controld_control.c:621
 msgid ""
 "*** Advanced Use Only *** Enabling this option will slow down cluster "
 "recovery under all conditions"
 msgstr "*** Advanced Use Only *** 启用此选项将在所有情况下减慢集群恢复的速度"
 
 #: daemons/controld/controld_control.c:623
 msgid ""
 "Delay cluster recovery for this much time to allow for additional events to "
 "occur. Useful if your configuration is sensitive to the order in which ping "
 "updates arrive."
 msgstr ""
 "集群恢复将被推迟指定的时间间隔,以等待更多事件发生。如果您的配置对 ping 更新"
 "到达的顺序很敏感,这就很有用"
 
 #: daemons/controld/controld_control.c:630
 #, fuzzy
 msgid ""
 "How long before nodes can be assumed to be safely down when watchdog-based "
 "self-fencing via SBD is in use"
 msgstr ""
 "当基于 watchdog 的自我 fence 机制通过SBD 被执行时,我们可以假设节点安全关闭之"
 "前需要等待多长时间"
 
 #: daemons/controld/controld_control.c:632
 msgid ""
 "If this is set to a positive value, lost nodes are assumed to self-fence "
 "using watchdog-based SBD within this much time. This does not require a "
 "fencing resource to be explicitly configured, though a fence_watchdog "
 "resource can be configured, to limit use to specific nodes. If this is set "
 "to 0 (the default), the cluster will never assume watchdog-based self-"
 "fencing. If this is set to a negative value, the cluster will use twice the "
 "local value of the `SBD_WATCHDOG_TIMEOUT` environment variable if that is "
 "positive, or otherwise treat this as 0. WARNING: When used, this timeout "
 "must be larger than `SBD_WATCHDOG_TIMEOUT` on all nodes that use watchdog-"
 "based SBD, and Pacemaker will refuse to start on any of those nodes where "
 "this is not true for the local value or SBD is not active. When this is set "
 "to a negative value, `SBD_WATCHDOG_TIMEOUT` must be set to the same value on "
 "all nodes that use SBD, otherwise data corruption or loss could occur."
 msgstr ""
 "如果设置为正值,则假定丢失的节点在这段时间内使用基于watchdog的SBD进行自我防"
 "护。这不需要明确配置fence资源,但可以配置一个fence_watchdog资源,以限制特定节"
 "点的使用。如果设置为0(默认值),集群将永远不会假定基于watchdog的自我防护。如"
 "果设置为负值,且如果`SBD_WATCHDOG_TIMEOUT`环境变量的本地值为正值,则集群将使"
 "用该值的两倍,否则将其视为0。警告:在使用基于watchdog的SBD的所有节点上,此超"
 "时必须大于`SBD_WATCGDOG_TIMEOUT`,如果本地值不是这样,或者SBD未运行,则"
 "Pacemaker将拒绝在任何节点上启动。如果设置为负值,则在使用SBD的所有节点上,"
 "`SBD_WATCHDOG_TIMEOUT`必须设置为相同的值,否则可能会发生数据损坏或丢失。"
 
 #: daemons/controld/controld_control.c:651
 msgid ""
 "How many times fencing can fail before it will no longer be immediately re-"
 "attempted on a target"
 msgstr "fence操作失败多少次会停止立即尝试"
 
 #: daemons/fenced/pacemaker-fenced.c:1389
 msgid "Advanced use only: An alternate parameter to supply instead of 'port'"
 msgstr "仅高级使用:使用替代的参数名,而不是'port'"
 
 #: daemons/fenced/pacemaker-fenced.c:1390
 msgid ""
 "some devices do not support the standard 'port' parameter or may provide "
 "additional ones. Use this to specify an alternate, device-specific, "
 "parameter that should indicate the machine to be fenced. A value of none can "
 "be used to tell the cluster not to supply any additional parameters."
 msgstr ""
 "一些设备不支持标准的'port'参数,或者可能提供其他参数。使用此选项可指定一个该"
 "设备专用的参数名,该参数用于标识需要fence的机器。值none可以用于告诉集群不要提"
 "供任何其他的参数。"
 
 #: daemons/fenced/pacemaker-fenced.c:1399
 msgid ""
 "A mapping of host names to ports numbers for devices that do not support "
 "host names."
 msgstr "为不支持主机名的设备提供主机名到端口号的映射。"
 
 #: daemons/fenced/pacemaker-fenced.c:1400
 msgid ""
 "Eg. node1:1;node2:2,3 would tell the cluster to use port 1 for node1 and "
 "ports 2 and 3 for node2"
 msgstr ""
 "例如 node1:1;node2:2,3,将会告诉集群对node1使用端口1,对node2使用端口2和3 "
 
 #: daemons/fenced/pacemaker-fenced.c:1404
 msgid "Eg. node1,node2,node3"
 msgstr "例如 node1,node2,node3"
 
 #: daemons/fenced/pacemaker-fenced.c:1405
 msgid ""
 "A list of machines controlled by this device (Optional unless "
 "pcmk_host_list=static-list)"
 msgstr "该设备控制的机器列表(可选参数,除非 pcmk_host_list 设置为 static-list)"
 
 #: daemons/fenced/pacemaker-fenced.c:1410
 msgid "How to determine which machines are controlled by the device."
 msgstr "如何确定设备控制哪些机器。"
 
 #: daemons/fenced/pacemaker-fenced.c:1411
 msgid ""
 "Allowed values: dynamic-list (query the device via the 'list' command), "
 "static-list (check the pcmk_host_list attribute), status (query the device "
 "via the 'status' command), none (assume every device can fence every machine)"
 msgstr ""
 "允许的值:dynamic-list(通过'list'命令查询设备),static-list(检查"
 "pcmk_host_list属性),status(通过'status'命令查询设备),none(假设每个设备"
 "都可fence 每台机器 )"
 
 #: daemons/fenced/pacemaker-fenced.c:1420
 #: daemons/fenced/pacemaker-fenced.c:1429
 msgid "Enable a base delay for fencing actions and specify base delay value."
 msgstr "在执行 fencing 操作前启用不超过指定时间的延迟。"
 
 #: daemons/fenced/pacemaker-fenced.c:1421
 msgid ""
 "Enable a delay of no more than the time specified before executing fencing "
 "actions. Pacemaker derives the overall delay by taking the value of "
 "pcmk_delay_base and adding a random delay value such that the sum is kept "
 "below this maximum."
 msgstr ""
 "在执行 fencing 操作前启用不超过指定时间的延迟。 Pacemaker通过获取"
 "pcmk_delay_base的值并添加随机延迟值来得出总体延迟,从而使总和保持在此最大值以"
 "下。"
 
 #: daemons/fenced/pacemaker-fenced.c:1431
 msgid ""
 "This enables a static delay for fencing actions, which can help avoid "
 "\"death matches\" where two nodes try to fence each other at the same time. "
 "If pcmk_delay_max  is also used, a random delay will be added such that the "
 "total delay is kept below that value.This can be set to a single time value "
 "to apply to any node targeted by this device (useful if a separate device is "
 "configured for each target), or to a node map (for example, \"node1:1s;"
 "node2:5\") to set a different value per target."
 msgstr ""
 "这使fencing 操作启用静态延迟,这可以帮助避免\"death matches\"即两个节点试图同"
 "时互相fence.如果还使用了pcmk_delay_max,则将添加随机延迟,以使总延迟保持在该"
 "值以下。可以将其设置为单个时间值,以应用于该设备针对的任何节点(适用于为每个"
 "目标分别配置了各自的设备的情况), 或着设置为一个节点映射 (例如,\"node1:1s;"
 "node2:5\")从而为每个目标设置不同值。"
 
 #: daemons/fenced/pacemaker-fenced.c:1443
 msgid ""
 "The maximum number of actions can be performed in parallel on this device"
 msgstr "可以在该设备上并发执行的最多操作数量"
 
 #: daemons/fenced/pacemaker-fenced.c:1444
 msgid ""
 "Cluster property concurrent-fencing=true needs to be configured first.Then "
 "use this to specify the maximum number of actions can be performed in "
 "parallel on this device. -1 is unlimited."
 msgstr ""
 "需要首先配置集群属性 concurrent-fencing=true 。然后使用此参数指定可以在该设备"
 "上并发执行的最多操作数量。 -1 代表没有限制"
 
 #: daemons/fenced/pacemaker-fenced.c:1449
 msgid "Advanced use only: An alternate command to run instead of 'reboot'"
 msgstr "仅高级使用:运行替代命令,而不是'reboot'"
 
 #: daemons/fenced/pacemaker-fenced.c:1450
 msgid ""
 "Some devices do not support the standard commands or may provide additional "
 "ones.\n"
 "Use this to specify an alternate, device-specific, command that implements "
 "the 'reboot' action."
 msgstr ""
 "一些设备不支持标准命令或可能提供其他命令,使用此选项可以指定一个该设备特定的"
 "替代命令,用来实现'reboot'操作。"
 
 #: daemons/fenced/pacemaker-fenced.c:1455
 msgid ""
 "Advanced use only: Specify an alternate timeout to use for reboot actions "
 "instead of stonith-timeout"
 msgstr "仅高级使用:指定用于'reboot' 操作的替代超时,而不是stonith-timeout"
 
 #: daemons/fenced/pacemaker-fenced.c:1456
 msgid ""
 "Some devices need much more/less time to complete than normal.Use this to "
 "specify an alternate, device-specific, timeout for 'reboot' actions."
 msgstr ""
 "一些设备需要比正常情况下更多或更少的时间来完成操作,使用此选项指定一个用"
 "于'reboot'操作的该设备特定的替代超时。"
 
 #: daemons/fenced/pacemaker-fenced.c:1461
 msgid ""
 "Advanced use only: The maximum number of times to retry the 'reboot' command "
 "within the timeout period"
 msgstr "仅高级使用:在超时前重试'reboot'命令的最大次数"
 
 #: daemons/fenced/pacemaker-fenced.c:1462
 msgid ""
 "Some devices do not support multiple connections. Operations may 'fail' if "
 "the device is busy with another task so Pacemaker will automatically retry "
 "the operation,      if there is time remaining. Use this option to alter the "
 "number of times Pacemaker retries 'reboot' actions before giving up."
 msgstr ""
 "一些设备不支持多个连接。 如果设备忙于另一个任务,则操作可能会'失败' ,因此"
 "Pacemaker将自动重试(如果时间允许)。 使用此选项更改Pacemaker在放弃之前重"
 "试'reboot' 操作的次数."
 
 #: daemons/fenced/pacemaker-fenced.c:1468
 msgid "Advanced use only: An alternate command to run instead of 'off'"
 msgstr "仅高级使用:运行替代命令,而不是'off'"
 
 #: daemons/fenced/pacemaker-fenced.c:1469
 msgid ""
 "Some devices do not support the standard commands or may provide additional "
 "ones.Use this to specify an alternate, device-specific, command that "
 "implements the 'off' action."
 msgstr ""
 "一些设备不支持标准命令或可能提供其他命令,使用此选项可指定一个该设备专用的替代"
 "命令,用来实现'off'操作。"
 
 #: daemons/fenced/pacemaker-fenced.c:1474
 msgid ""
 "Advanced use only: Specify an alternate timeout to use for off actions "
 "instead of stonith-timeout"
 msgstr "仅高级使用:指定用于off 操作的替代超时,而不是stonith-timeout"
 
 #: daemons/fenced/pacemaker-fenced.c:1475
 msgid ""
 "Some devices need much more/less time to complete than normal.Use this to "
 "specify an alternate, device-specific, timeout for 'off' actions."
 msgstr ""
 "一些设备需要比正常情况下更多或更少的时间来完成操作,使用此选项指定一个用"
 "于'off'操作的该设备特定的替代超时。"
 
 #: daemons/fenced/pacemaker-fenced.c:1480
 msgid ""
 "Advanced use only: The maximum number of times to retry the 'off' command "
 "within the timeout period"
 msgstr "仅高级使用:在超时前重试'off'命令的最大次数"
 
 #: daemons/fenced/pacemaker-fenced.c:1481
 msgid ""
 "Some devices do not support multiple connections. Operations may 'fail' if "
 "the device is busy with another task so Pacemaker will automatically retry "
 "the operation,      if there is time remaining. Use this option to alter the "
 "number of times Pacemaker retries 'off' actions before giving up."
 msgstr ""
 " 一些设备不支持多个连接。 如果设备忙于另一个任务,则操作可能会'失败' , 因此"
 "Pacemaker将自动重试(如果时间允许)。 使用此选项更改Pacemaker在放弃之前重"
 "试'off' 操作的次数."
 
 #: daemons/fenced/pacemaker-fenced.c:1487
 msgid "Advanced use only: An alternate command to run instead of 'on'"
 msgstr "仅高级使用:运行替代命令,而不是'on'"
 
 #: daemons/fenced/pacemaker-fenced.c:1488
 msgid ""
 "Some devices do not support the standard commands or may provide additional "
 "ones.Use this to specify an alternate, device-specific, command that "
 "implements the 'on' action."
 msgstr ""
 "一些设备不支持标准命令或可能提供其他命令,使用此选项可指定一个该设备特定的替"
 "代命令,用来实现'on'操作。"
 
 #: daemons/fenced/pacemaker-fenced.c:1493
 msgid ""
 "Advanced use only: Specify an alternate timeout to use for on actions "
 "instead of stonith-timeout"
 msgstr "仅高级使用:指定用于on 操作的替代超时,而不是stonith-timeout"
 
 #: daemons/fenced/pacemaker-fenced.c:1494
 msgid ""
 "Some devices need much more/less time to complete than normal.Use this to "
 "specify an alternate, device-specific, timeout for 'on' actions."
 msgstr ""
 "一些设备需要比正常情况下更多或更少的时间来完成操作,使用此选项指定一个用"
 "于'on'操作的该设备特定的替代超时。"
 
 #: daemons/fenced/pacemaker-fenced.c:1499
 msgid ""
 "Advanced use only: The maximum number of times to retry the 'on' command "
 "within the timeout period"
 msgstr "仅高级使用:在超时前重试'on'命令的最大次数"
 
 #: daemons/fenced/pacemaker-fenced.c:1500
 msgid ""
 "Some devices do not support multiple connections. Operations may 'fail' if "
 "the device is busy with another task so Pacemaker will automatically retry "
 "the operation,      if there is time remaining. Use this option to alter the "
 "number of times Pacemaker retries 'on' actions before giving up."
 msgstr ""
 " 一些设备不支持多个连接。 如果设备忙于另一个任务,则操作可能会'失败' , 因此"
 "Pacemaker将自动重试(如果时间允许)。 使用此选项更改Pacemaker在放弃之前重"
 "试'on' 操作的次数."
 
 #: daemons/fenced/pacemaker-fenced.c:1506
 msgid "Advanced use only: An alternate command to run instead of 'list'"
 msgstr "仅高级使用:运行替代命令,而不是'list'"
 
 #: daemons/fenced/pacemaker-fenced.c:1507
 msgid ""
 "Some devices do not support the standard commands or may provide additional "
 "ones.Use this to specify an alternate, device-specific, command that "
 "implements the 'list' action."
 msgstr ""
 "一些设备不支持标准命令或可能提供其他命令,使用此选项可指定一个该设备特定的替"
 "代命令,用来实现'list'操作。"
 
 #: daemons/fenced/pacemaker-fenced.c:1512
 msgid ""
 "Advanced use only: Specify an alternate timeout to use for list actions "
 "instead of stonith-timeout"
 msgstr "仅高级使用:指定用于list 操作的替代超时,而不是stonith-timeout"
 
 #: daemons/fenced/pacemaker-fenced.c:1513
 msgid ""
 "Some devices need much more/less time to complete than normal.Use this to "
 "specify an alternate, device-specific, timeout for 'list' actions."
 msgstr ""
 "一些设备需要比正常情况下更多或更少的时间来完成操作,使用此选项指定一个用"
 "于'list'操作的该设备特定的替代超时。"
 
 #: daemons/fenced/pacemaker-fenced.c:1518
 msgid ""
 "Advanced use only: The maximum number of times to retry the 'list' command "
 "within the timeout period"
 msgstr "仅高级使用:在超时前重试'list'命令的最大次数"
 
 #: daemons/fenced/pacemaker-fenced.c:1519
 msgid ""
 "Some devices do not support multiple connections. Operations may 'fail' if "
 "the device is busy with another task so Pacemaker will automatically retry "
 "the operation,      if there is time remaining. Use this option to alter the "
 "number of times Pacemaker retries 'list' actions before giving up."
 msgstr ""
 " 一些设备不支持多个连接。 如果设备忙于另一个任务,则操作可能会'失败' , 因此"
 "Pacemaker将自动重试(如果时间允许)。 使用此选项更改Pacemaker在放弃之前重"
 "试'list' 操作的次数."
 
 #: daemons/fenced/pacemaker-fenced.c:1525
 msgid "Advanced use only: An alternate command to run instead of 'monitor'"
 msgstr "仅高级使用:运行替代命令,而不是'monitor'"
 
 #: daemons/fenced/pacemaker-fenced.c:1526
 msgid ""
 "Some devices do not support the standard commands or may provide additional "
 "ones.Use this to specify an alternate, device-specific, command that "
 "implements the 'monitor' action."
 msgstr ""
 "一些设备不支持标准命令或可能提供其他命令,使用此选项可指定一个该设备特定的替"
 "代命令,用来实现'monitor'操作。"
 
 #: daemons/fenced/pacemaker-fenced.c:1531
 msgid ""
 "Advanced use only: Specify an alternate timeout to use for monitor actions "
 "instead of stonith-timeout"
 msgstr "仅高级使用:指定用于monitor 操作的替代超时,而不是stonith-timeout"
 
 #: daemons/fenced/pacemaker-fenced.c:1532
 msgid ""
 "Some devices need much more/less time to complete than normal.\n"
 "Use this to specify an alternate, device-specific, timeout for 'monitor' "
 "actions."
 msgstr ""
 "一些设备需要比正常情况下更多或更少的时间来完成操作,使用此选项指定一个用"
 "于'monitor'操作的该设备特定的替代超时。"
 
 #: daemons/fenced/pacemaker-fenced.c:1537
 msgid ""
 "Advanced use only: The maximum number of times to retry the 'monitor' "
 "command within the timeout period"
 msgstr "仅高级使用:在超时前重试'monitor'命令的最大次数"
 
 #: daemons/fenced/pacemaker-fenced.c:1538
 msgid ""
 "Some devices do not support multiple connections. Operations may 'fail' if "
 "the device is busy with another task so Pacemaker will automatically retry "
 "the operation,      if there is time remaining. Use this option to alter the "
 "number of times Pacemaker retries 'monitor' actions before giving up."
 msgstr ""
 " 一些设备不支持多个连接。 如果设备忙于另一个任务,则操作可能会'失败' , 因此"
 "Pacemaker将自动重试(如果时间允许)。 使用此选项更改Pacemaker在放弃之前重"
 "试'monitor' 操作的次数."
 
 #: daemons/fenced/pacemaker-fenced.c:1544
 msgid "Advanced use only: An alternate command to run instead of 'status'"
 msgstr "仅高级使用:运行替代命令,而不是'status'"
 
 #: daemons/fenced/pacemaker-fenced.c:1545
 msgid ""
 "Some devices do not support the standard commands or may provide additional "
 "ones.Use this to specify an alternate, device-specific, command that "
 "implements the 'status' action."
 msgstr ""
 "一些设备不支持标准命令或可能提供其他命令,使用此选项可指定一个该设备特定的替"
 "代命令,用来实现'status'操作。"
 
 #: daemons/fenced/pacemaker-fenced.c:1550
 msgid ""
 "Advanced use only: Specify an alternate timeout to use for status actions "
 "instead of stonith-timeout"
 msgstr "仅高级使用:指定用于status 操作的替代超时,而不是stonith-timeout"
 
 #: daemons/fenced/pacemaker-fenced.c:1551
 msgid ""
 "Some devices need much more/less time to complete than normal.Use this to "
 "specify an alternate, device-specific, timeout for 'status' actions."
 msgstr ""
 "一些设备需要比正常情况下更多或更少的时间来完成操作,使用此选项指定一个用"
 "于'status'操作的该设备特定的替代超时"
 
 #: daemons/fenced/pacemaker-fenced.c:1556
 msgid ""
 "Advanced use only: The maximum number of times to retry the 'status' command "
 "within the timeout period"
 msgstr "仅高级使用:在超时前重试'status'命令的最大次数"
 
 #: daemons/fenced/pacemaker-fenced.c:1557
 msgid ""
 "Some devices do not support multiple connections. Operations may 'fail' if "
 "the device is busy with another task so Pacemaker will automatically retry "
 "the operation,      if there is time remaining. Use this option to alter the "
 "number of times Pacemaker retries 'status' actions before giving up."
 msgstr ""
 " 一些设备不支持多个连接。 如果设备忙于另一个任务,则操作可能会'失败' , 因此"
 "Pacemaker将自动重试(如果时间允许)。 使用此选项更改Pacemaker在放弃之前重"
 "试'status' 操作的次数."
 
 #: daemons/fenced/pacemaker-fenced.c:1566
 msgid "Instance attributes available for all \"stonith\"-class resources"
 msgstr " 可用于所有stonith类资源的实例属性"
 
 #: daemons/fenced/pacemaker-fenced.c:1568
 msgid ""
 "Instance attributes available for all \"stonith\"-class resources and used "
 "by Pacemaker's fence daemon, formerly known as stonithd"
 msgstr ""
 " 可用于所有stonith类资源的实例属性,并由Pacemaker的fence守护程序使用(以前称"
 "为stonithd)"
 
 #: lib/cib/cib_utils.c:559
 msgid "Enable Access Control Lists (ACLs) for the CIB"
 msgstr "为CIB启用访问控制列表(ACL)"
 
 #: lib/cib/cib_utils.c:565
 msgid "Maximum IPC message backlog before disconnecting a cluster daemon"
 msgstr "断开集群守护程序之前的最大IPC消息积压"
 
 #: lib/cib/cib_utils.c:566
 msgid ""
 "Raise this if log has \"Evicting client\" messages for cluster daemon PIDs "
 "(a good value is the number of resources in the cluster multiplied by the "
 "number of nodes)."
 msgstr ""
 "如果日志中有针对集群守护程序PID的消息“Evicting client”,(则建议将值设为集群"
 "中的资源数量乘以节点数量)"
 
 #: lib/common/options.c:633
 msgid "  Allowed values: "
 msgstr " 允许的值: "
 
 #: lib/common/cmdline.c:71
 msgid "Display software version and exit"
 msgstr "显示软件版本信息"
 
 #: lib/common/cmdline.c:74
 msgid "Increase debug output (may be specified multiple times)"
 msgstr "显示更多调试信息(可多次指定)"
 
 #: lib/common/cmdline.c:92
 msgid "FORMAT"
 msgstr "格式"
 
 #: lib/common/cmdline.c:94
 msgid "Specify file name for output (or \"-\" for stdout)"
 msgstr "指定输出的文件名 或指定'-' 表示标准输出"
 
 #: lib/common/cmdline.c:94
 msgid "DEST"
 msgstr "目标"
 
 #: lib/common/cmdline.c:100
 msgid "Output Options:"
 msgstr "输出选项"
 
 #: lib/common/cmdline.c:100
 msgid "Show output help"
 msgstr "显示输出帮助"
 
 #: lib/pengine/common.c:39
 msgid "What to do when the cluster does not have quorum"
 msgstr "当集群没有必需票数时该如何作"
 
 #: lib/pengine/common.c:45
 msgid "Whether resources can run on any node by default"
 msgstr "资源是否默认可以在任何节点上运行"
 
 #: lib/pengine/common.c:51
 msgid ""
 "Whether the cluster should refrain from monitoring, starting, and stopping "
 "resources"
 msgstr "集群是否应避免监视,启动和停止资源"
 
 #: lib/pengine/common.c:58
 msgid ""
 "Whether a start failure should prevent a resource from being recovered on "
 "the same node"
 msgstr "是否避免在同一节点上重启启动失败的资源"
 
 #: lib/pengine/common.c:60
 msgid ""
 "When true, the cluster will immediately ban a resource from a node if it "
 "fails to start there. When false, the cluster will instead check the "
 "resource's fail count against its migration-threshold."
 msgstr ""
 "当为true,如果资源启动失败,集群将立即禁止节点启动该资源,当为false,群集将根"
 "据其迁移阈值来检查资源的失败计数。"
 
 #: lib/pengine/common.c:67
 msgid "Whether the cluster should check for active resources during start-up"
 msgstr "群集是否在启动期间检查运行资源"
 
 #: lib/pengine/common.c:73
 msgid "Whether to lock resources to a cleanly shut down node"
 msgstr "是否锁定资源到完全关闭的节点"
 
 #: lib/pengine/common.c:74
 msgid ""
 "When true, resources active on a node when it is cleanly shut down are kept "
 "\"locked\" to that node (not allowed to run elsewhere) until they start "
 "again on that node after it rejoins (or for at most shutdown-lock-limit, if "
 "set). Stonith resources and Pacemaker Remote connections are never locked. "
 "Clone and bundle instances and the promoted role of promotable clones are "
 "currently never locked, though support could be added in a future release."
 msgstr ""
 "设置为true时,在完全关闭的节点上活动的资源将被“锁定”到该节点(不允许在其他地"
 "方运行),直到该节点重新加入后资源重新启动(或最长shutdown-lock-limit,如果已"
 "设置)。 Stonith资源和Pacemaker Remote连接永远不会被锁定。 克隆和捆绑实例以及"
 "可升级克隆的主角色目前从未锁定,尽管可以在将来的发行版中添加支持。"
 
 #: lib/pengine/common.c:85
 msgid "Do not lock resources to a cleanly shut down node longer than this"
 msgstr "资源会被锁定到完全关闭的节点的最长时间"
 
 #: lib/pengine/common.c:86
 msgid ""
 "If shutdown-lock is true and this is set to a nonzero time duration, "
 "shutdown locks will expire after this much time has passed since the "
 "shutdown was initiated, even if the node has not rejoined."
 msgstr ""
 "如果shutdown-lock为true,并且将此选项设置为非零持续时间,则自从开始shutdown以"
 "来经过了这么长的时间后,shutdown锁将过期,即使该节点尚未重新加入。"
 
 #: lib/pengine/common.c:95
 msgid ""
 "*** Advanced Use Only *** Whether nodes may be fenced as part of recovery"
 msgstr "*** Advanced Use Only *** 节点是否可以被 fence 以作为集群恢复的一部分"
 
 #: lib/pengine/common.c:97
 msgid ""
 "If false, unresponsive nodes are immediately assumed to be harmless, and "
 "resources that were active on them may be recovered elsewhere. This can "
 "result in a \"split-brain\" situation, potentially leading to data loss and/"
 "or service unavailability."
 msgstr ""
 "如果为false,则立即假定无响应的节点是无害的,并且可以在其他位置恢复在其上活动"
 "的资源。 这可能会导致 \"split-brain\" 情况,可能导致数据丢失和/或服务不可用。"
 
 #: lib/pengine/common.c:105
 msgid ""
 "Action to send to fence device when a node needs to be fenced (\"poweroff\" "
 "is a deprecated alias for \"off\")"
 msgstr "发送到 fence 设备的操作( \"poweroff\" 是 \"off \"的别名,不建议使用)"
 
 #: lib/pengine/common.c:112
 msgid "*** Advanced Use Only *** Unused by Pacemaker"
 msgstr "*** Advanced Use Only *** pacemaker未使用"
 
 #: lib/pengine/common.c:113
 msgid ""
 "This value is not used by Pacemaker, but is kept for backward compatibility, "
 "and certain legacy fence agents might use it."
 msgstr ""
 "Pacemaker不使用此值,但保留此值是为了向后兼容,某些传统的fence 代理可能会使用"
 "它。"
 
 #: lib/pengine/common.c:119
 msgid "Whether watchdog integration is enabled"
 msgstr "是否启用watchdog集成设置"
 
 #: lib/pengine/common.c:120
 msgid ""
 "This is set automatically by the cluster according to whether SBD is "
 "detected to be in use. User-configured values are ignored. The value `true` "
 "is meaningful if diskless SBD is used and `stonith-watchdog-timeout` is "
 "nonzero. In that case, if fencing is required, watchdog-based self-fencing "
 "will be performed via SBD without requiring a fencing resource explicitly "
 "configured."
 msgstr ""
 "这是由集群检测是否正在使用 SBD 并自动设置。用户配置的值将被忽略。如果使用无"
 "盘 SBD 并且 stonith-watchdog-timeout 不为零时,此选项为 true 才有实际意义。在"
 "这种情况下,无需明确配置fence资源,如果需要fence时,基于watchdog的自我fence会"
 "通过SBD执行。"
 
 #: lib/pengine/common.c:130
 msgid "Allow performing fencing operations in parallel"
 msgstr "允许并行执行 fencing 操作"
 
 #: lib/pengine/common.c:136
 msgid "*** Advanced Use Only *** Whether to fence unseen nodes at start-up"
 msgstr "*** 仅高级使用 *** 是否在启动时fence不可见节点"
 
 #: lib/pengine/common.c:137
 msgid ""
 "Setting this to false may lead to a \"split-brain\" situation,potentially "
 "leading to data loss and/or service unavailability."
 msgstr ""
 "将此设置为 false 可能会导致 \"split-brain\" 的情况,可能导致数据丢失和/或服务"
 "不可用。"
 
 #: lib/pengine/common.c:143
 msgid ""
 "Apply fencing delay targeting the lost nodes with the highest total resource "
 "priority"
 msgstr "针对具有最高总资源优先级的丢失节点应用fencing延迟"
 
 #: lib/pengine/common.c:144
 msgid ""
 "Apply specified delay for the fencings that are targeting the lost nodes "
 "with the highest total resource priority in case we don't have the majority "
 "of the nodes in our cluster partition, so that the more significant nodes "
 "potentially win any fencing match, which is especially meaningful under "
 "split-brain of 2-node cluster. A promoted resource instance takes the base "
 "priority + 1 on calculation if the base priority is not 0. Any static/random "
 "delays that are introduced by `pcmk_delay_base/max` configured for the "
 "corresponding fencing resources will be added to this delay. This delay "
 "should be significantly greater than, safely twice, the maximum "
 "`pcmk_delay_base/max`. By default, priority fencing delay is disabled."
 msgstr ""
 "如果我们所在的集群分区并不拥有大多数集群节点,则针对丢失节点的fence操作应用指"
 "定的延迟,这样更重要的节点就能够赢得fence竞赛。这对于双节点集群在split-brain"
 "状况下尤其有意义。如果基本优先级不为0,在计算时主资源实例获得基本优先级+1。任"
 "何对于相应的 fence 资源由 pcmk_delay_base/max 配置所引入的静态/随机延迟会被添"
 "加到此延迟。为了安全, 这个延迟应该明显大于 pcmk_delay_base/max 的最大设置值,"
 "例如两倍。默认情况下,优先级fencing延迟已禁用。"
 
 #: lib/pengine/common.c:161
 msgid "Maximum time for node-to-node communication"
 msgstr "最大节点间通信时间"
 
 #: lib/pengine/common.c:162
 msgid ""
 "The node elected Designated Controller (DC) will consider an action failed "
 "if it does not get a response from the node executing the action within this "
 "time (after considering the action's own timeout). The \"correct\" value "
 "will depend on the speed and load of your network and cluster nodes."
 msgstr ""
 "如果一个操作未在该时间内(并且考虑操作本身的超时时长)从执行该操作的节点获得"
 "响应,则会被选为指定控制器(DC)的节点认定为失败。\"正确\" 值将取决于速度和您"
 "的网络和集群节点的负载。"
 
 #: lib/pengine/common.c:189
 #, fuzzy
 msgid "Whether the cluster should stop all active resources"
 msgstr "群集是否在启动期间检查运行资源"
 
 #: lib/pengine/common.c:195
 msgid "Whether to stop resources that were removed from the configuration"
 msgstr "是否停止配置已被删除的资源"
 
 #: lib/pengine/common.c:201
 msgid "Whether to cancel recurring actions removed from the configuration"
 msgstr "是否取消配置已被删除的的重复操作"
 
 #: lib/pengine/common.c:207
 msgid ""
 "*** Deprecated *** Whether to remove stopped resources from the executor"
 msgstr "***不推荐***是否从pacemaker-execd 守护进程中清除已停止的资源"
 
+#: tools/crm_resource.c:257
+#, c-format
+msgid "Aborting because no messages received in %d seconds"
+msgstr "中止,因为在%d秒内没有接收到消息"
+
+#: tools/crm_resource.c:908
+#, c-format
+msgid "Invalid check level setting: %s"
+msgstr "无效的检查级别设置:%s"
+
+#: tools/crm_resource.c:992
+#, c-format
+msgid ""
+"Resource '%s' not moved: active in %d locations (promoted in %d).\n"
+"To prevent '%s' from running on a specific location, specify a node.To "
+"prevent '%s' from being promoted at a specific location, specify a node and "
+"the --promoted option."
+msgstr ""
+"资源'%s'未移动:在%d个位置运行(其中在%d个位置为主实例)\n"
+"若要阻止'%s'在特定位置运行,请指定一个节点。若要防止'%s'在指定位置升级,指定"
+"一个节点并使用--promoted选项"
+
+#: tools/crm_resource.c:1003
+#, c-format
+msgid ""
+"Resource '%s' not moved: active in %d locations.\n"
+"To prevent '%s' from running on a specific location, specify a node."
+msgstr ""
+"资源%s未移动:在%d个位置运行\n"
+"若要防止'%s'运行在特定位置,指定一个节点"
+
+#: tools/crm_resource.c:1078
+#, c-format
+msgid "Could not get modified CIB: %s\n"
+msgstr "无法获得修改的CIB:%s\n"
+
+#: tools/crm_resource.c:1112
+msgid "You need to specify a resource type with -t"
+msgstr "需要使用-t指定资源类型"
+
+#: tools/crm_resource.c:1155
+#, c-format
+msgid "No agents found for standard '%s'"
+msgstr "没有发现指定的'%s'标准代理"
+
+#: tools/crm_resource.c:1158
+#, fuzzy, c-format
+msgid "No agents found for standard '%s' and provider '%s'"
+msgstr "没有发现指定的标准%s和提供者%S的资源代理"
+
+#: tools/crm_resource.c:1225
+#, c-format
+msgid "No %s found for %s"
+msgstr "没有发现%s符合%s"
+
+#: tools/crm_resource.c:1230
+#, c-format
+msgid "No %s found"
+msgstr "没有发现%s"
+
+#: tools/crm_resource.c:1290
+#, c-format
+msgid "No cluster connection to Pacemaker Remote node %s detected"
+msgstr "未检测到至pacemaker远程节点%s的集群连接"
+
+#: tools/crm_resource.c:1351
+msgid "Must specify -t with resource type"
+msgstr "需要使用-t指定资源类型"
+
+#: tools/crm_resource.c:1357
+msgid "Must supply -v with new value"
+msgstr "必须使用-v指定新值"
+
+#: tools/crm_resource.c:1389
+msgid "Could not create executor connection"
+msgstr "无法创建到pacemaker-execd守护进程的连接"
+
 #: tools/crm_resource.c:1414
 #, fuzzy, c-format
 msgid "Metadata query for %s failed: %s"
 msgstr ",查询%s的元数据失败: %s\n"
 
 #: tools/crm_resource.c:1420
 #, c-format
 msgid "'%s' is not a valid agent specification"
 msgstr "'%s' 是一个无效的代理"
 
+#: tools/crm_resource.c:1433
+msgid "--resource cannot be used with --class, --agent, and --provider"
+msgstr "--resource 不能与 --class, --agent, --provider一起使用"
+
+#: tools/crm_resource.c:1438
+msgid ""
+"--class, --agent, and --provider can only be used with --validate and --"
+"force-*"
+msgstr "--class, --agent和--provider只能被用于--validate和--force-*"
+
+#: tools/crm_resource.c:1447
+msgid "stonith does not support providers"
+msgstr "stonith 不支持提供者"
+
+#: tools/crm_resource.c:1451
+#, c-format
+msgid "%s is not a known stonith agent"
+msgstr "%s 不是一个已知stonith代理"
+
+#: tools/crm_resource.c:1456
+#, c-format
+msgid "%s:%s:%s is not a known resource"
+msgstr "%s:%s:%s 不是一个已知资源"
+
+#: tools/crm_resource.c:1570
+#, c-format
+msgid "Error creating output format %s: %s"
+msgstr "创建输出格式错误 %s:%s"
+
+#: tools/crm_resource.c:1597
+msgid "--expired requires --clear or -U"
+msgstr "--expired需要和--clear或-U一起使用"
+
+#: tools/crm_resource.c:1614
+#, c-format
+msgid "Error parsing '%s' as a name=value pair"
+msgstr "'%s'解析错误,格式为name=value"
+
+#: tools/crm_resource.c:1711
+msgid "Must supply a resource id with -r"
+msgstr "必须使用-r指定资源id"
+
+#: tools/crm_resource.c:1717
+msgid "Must supply a node name with -N"
+msgstr "必须使用-N指定节点名称"
+
+#: tools/crm_resource.c:1741
+msgid "Could not create CIB connection"
+msgstr "无法创建到CIB的连接"
+
+#: tools/crm_resource.c:1749
+#, c-format
+msgid "Could not connect to the CIB: %s"
+msgstr "不能连接到CIB:%s"
+
+#: tools/crm_resource.c:1770
+#, c-format
+msgid "Resource '%s' not found"
+msgstr "没有发现'%s'资源"
+
+#: tools/crm_resource.c:1782
+#, c-format
+msgid "Cannot operate on clone resource instance '%s'"
+msgstr "不能操作克隆资源实例'%s'"
+
+#: tools/crm_resource.c:1794
+#, c-format
+msgid "Node '%s' not found"
+msgstr "没有发现%s节点"
+
+#: tools/crm_resource.c:1805 tools/crm_resource.c:1814
+#, c-format
+msgid "Error connecting to the controller: %s"
+msgstr "连接到控制器错误:%s"
+
+#: tools/crm_resource.c:2050
+msgid "You need to supply a value with the -v option"
+msgstr "需要使用-v选项提供一个值"
+
+#: tools/crm_resource.c:2105
+#, c-format
+msgid "Unimplemented command: %d"
+msgstr "无效的命令:%d"
+
+#: tools/crm_resource.c:2139
+#, c-format
+msgid "Error performing operation: %s"
+msgstr "执行操作错误:%s"
+
 #~ msgid ""
 #~ "If nonzero, along with `have-watchdog=true` automatically set by the "
 #~ "cluster, when fencing is required, watchdog-based self-fencing will be "
 #~ "performed via SBD without requiring a fencing resource explicitly "
 #~ "configured. If `stonith-watchdog-timeout` is set to a positive value, "
 #~ "unseen nodes are assumed to self-fence within this much time. +WARNING:+ "
 #~ "It must be ensured that this value is larger than the "
 #~ "`SBD_WATCHDOG_TIMEOUT` environment variable on all nodes. Pacemaker "
 #~ "verifies the settings individually on all nodes and prevents startup or "
 #~ "shuts down if configured wrongly on the fly. It's strongly recommended "
 #~ "that `SBD_WATCHDOG_TIMEOUT` is set to the same value on all nodes. If "
 #~ "`stonith-watchdog-timeout` is set to a negative value, and "
 #~ "`SBD_WATCHDOG_TIMEOUT` is set, twice that value will be used. +WARNING:+ "
 #~ "In this case, it's essential (currently not verified by Pacemaker) that "
 #~ "`SBD_WATCHDOG_TIMEOUT` is set to the same value on all nodes."
 #~ msgstr ""
 #~ "如果值非零,且集群设置了 `have-watchdog=true` ,当需要 fence 操作时,基于 "
 #~ "watchdog 的自我 fence 机制将通过SBD执行,而不需要显式配置 fence 资源。如"
 #~ "果 `stonith-watchdog-timeout` 被设为正值,则假定不可见的节点在这段时间内自"
 #~ "我fence。 +WARNING:+ 必须确保该值大于所有节点上的`SBD_WATCHDOG_TIMEOUT` 环"
 #~ "境变量。Pacemaker将在所有节点上单独验证设置,如发现有错误的动态配置,将防"
 #~ "止节点启动或关闭。强烈建议在所有节点上将 `SBD_WATCHDOG_TIMEOUT` 设置为相同"
 #~ "的值。如果 `stonith-watchdog-timeout` 设置为负值。并且设置了 "
 #~ "`SBD_WATCHDOG_TIMEOUT` ,则将使用该值的两倍, +WARNING:+ 在这种情况下,必"
 #~ "须将所有节点上 `SBD_WATCHDOG_TIMEOUT` 设置为相同的值(目前没有通过pacemaker"
 #~ "验证)。"
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 73bc75fe8f..c1d3bcefc2 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -1,2172 +1,2172 @@
 /*
  * Copyright 2004-2022 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <crm_resource.h>
 #include <crm/lrmd_internal.h>
 #include <crm/common/cmdline_internal.h>
 #include <crm/common/ipc_attrd_internal.h>
 #include <crm/common/lists_internal.h>
 #include <crm/common/output.h>
 #include <pacemaker-internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
 #include <time.h>
 
 #include <crm/crm.h>
 #include <crm/stonith-ng.h>
 #include <crm/common/ipc_controld.h>
 #include <crm/cib/internal.h>
 
 #define SUMMARY "crm_resource - perform tasks related to Pacemaker cluster resources"
 
 enum rsc_command {
     cmd_none = 0,           // No command option given (yet)
     cmd_ban,
     cmd_cleanup,
     cmd_clear,
     cmd_colocations,
     cmd_cts,
     cmd_delete,
     cmd_delete_param,
     cmd_digests,
     cmd_execute_agent,
     cmd_fail,
     cmd_get_param,
     cmd_get_property,
     cmd_list_active_ops,
     cmd_list_agents,
     cmd_list_all_ops,
     cmd_list_alternatives,
     cmd_list_instances,
     cmd_list_providers,
     cmd_list_resources,
     cmd_list_standards,
     cmd_locate,
     cmd_metadata,
     cmd_move,
     cmd_query_raw_xml,
     cmd_query_xml,
     cmd_refresh,
     cmd_restart,
     cmd_set_param,
     cmd_set_property,
     cmd_wait,
     cmd_why,
 };
 
 struct {
     enum rsc_command rsc_cmd;     // crm_resource command to perform
 
     // Infrastructure that given command needs to work
     gboolean require_cib;         // Whether command requires CIB IPC
     int cib_options;              // Options to use with CIB IPC calls
     gboolean require_crmd;        // Whether command requires controller IPC
     gboolean require_dataset;     // Whether command requires populated data set
     gboolean require_resource;    // Whether command requires resource specified
     gboolean require_node;        // Whether command requires node specified
     int find_flags;               // Flags to use when searching for resource
 
     // Command-line option values
     gchar *rsc_id;                // Value of --resource
     gchar *rsc_type;              // Value of --resource-type
     gboolean force;               // --force was given
     gboolean clear_expired;       // --expired was given
     gboolean recursive;           // --recursive was given
     gboolean promoted_role_only;  // --promoted was given
     gchar *host_uname;            // Value of --node
     gchar *interval_spec;         // Value of --interval
     gchar *move_lifetime;         // Value of --lifetime
     gchar *operation;             // Value of --operation
     const char *attr_set_type;    // Instance, meta, or utilization attribute
     gchar *prop_id;               // --nvpair (attribute XML ID)
     char *prop_name;              // Attribute name
     gchar *prop_set;              // --set-name (attribute block XML ID)
     gchar *prop_value;            // --parameter-value (attribute value)
     int timeout_ms;               // Parsed from --timeout value
     char *agent_spec;             // Standard and/or provider and/or agent
     gchar *xml_file;              // Value of (deprecated) --xml-file
     int check_level;              // Optional value of --validate or --force-check
 
     // Resource configuration specified via command-line arguments
     gboolean cmdline_config;      // Resource configuration was via arguments
     char *v_agent;                // Value of --agent
     char *v_class;                // Value of --class
     char *v_provider;             // Value of --provider
     GHashTable *cmdline_params;   // Resource parameters specified
 
     // Positional command-line arguments
     gchar **remainder;            // Positional arguments as given
     GHashTable *override_params;  // Resource parameter values that override config
 } options = {
     .attr_set_type = XML_TAG_ATTR_SETS,
     .check_level = -1,
     .cib_options = cib_sync_call,
     .require_cib = TRUE,
     .require_dataset = TRUE,
     .require_resource = TRUE,
 };
 
 #if 0
 // @COMPAT @TODO enable this at next backward compatibility break
 #define SET_COMMAND(cmd) do {                                               \
         if (options.rsc_cmd != cmd_none) {                                  \
             g_set_error(error, PCMK__EXITC_ERROR, CRM_EX_USAGE,             \
                         "Only one command option may be specified");        \
             return FALSE;                                                   \
         }                                                                   \
         options.rsc_cmd = (cmd);                                            \
     } while (0)
 #else
 #define SET_COMMAND(cmd) do {                                               \
         if (options.rsc_cmd != cmd_none) {                                  \
             reset_options();                                                \
         }                                                                   \
         options.rsc_cmd = (cmd);                                            \
     } while (0)
 #endif
 
 gboolean agent_provider_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean attr_set_type_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean class_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean cleanup_refresh_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean delete_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean expired_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean list_agents_cb(const gchar *option_name, const gchar *optarg,
                         gpointer data, GError **error);
 gboolean list_providers_cb(const gchar *option_name, const gchar *optarg,
                            gpointer data, GError **error);
 gboolean list_standards_cb(const gchar *option_name, const gchar *optarg,
                            gpointer data, GError **error);
 gboolean list_alternatives_cb(const gchar *option_name, const gchar *optarg,
                               gpointer data, GError **error);
 gboolean metadata_cb(const gchar *option_name, const gchar *optarg,
                      gpointer data, GError **error);
 gboolean option_cb(const gchar *option_name, const gchar *optarg,
                    gpointer data, GError **error);
 gboolean fail_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean flag_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean get_param_prop_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean list_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean set_delete_param_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean set_prop_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean timeout_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean validate_or_force_cb(const gchar *option_name, const gchar *optarg,
                               gpointer data, GError **error);
 gboolean restart_cb(const gchar *option_name, const gchar *optarg,
                     gpointer data, GError **error);
 gboolean digests_cb(const gchar *option_name, const gchar *optarg,
                     gpointer data, GError **error);
 gboolean wait_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 gboolean why_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
 
 static crm_exit_t exit_code = CRM_EX_OK;
 static pcmk__output_t *out = NULL;
 static pcmk__common_args_t *args = NULL;
 
 // Things that should be cleaned up on exit
 static GError *error = NULL;
 static GMainLoop *mainloop = NULL;
 static cib_t *cib_conn = NULL;
 static pcmk_ipc_api_t *controld_api = NULL;
 static pe_working_set_t *data_set = NULL;
 
 #define MESSAGE_TIMEOUT_S 60
 
 #define INDENT "                                    "
 
 static pcmk__supported_format_t formats[] = {
     PCMK__SUPPORTED_FORMAT_NONE,
     PCMK__SUPPORTED_FORMAT_TEXT,
     PCMK__SUPPORTED_FORMAT_XML,
     { NULL, NULL, NULL }
 };
 
 // Clean up and exit
 static crm_exit_t
 bye(crm_exit_t ec)
 {
     pcmk__output_and_clear_error(error, out);
 
     if (out != NULL) {
         out->finish(out, ec, true, NULL);
         pcmk__output_free(out);
     }
 
     if (cib_conn != NULL) {
         cib_t *save_cib_conn = cib_conn;
 
         cib_conn = NULL; // Ensure we can't free this twice
         cib__clean_up_connection(&save_cib_conn);
     }
 
     if (controld_api != NULL) {
         pcmk_ipc_api_t *save_controld_api = controld_api;
 
         controld_api = NULL; // Ensure we can't free this twice
         pcmk_free_ipc_api(save_controld_api);
     }
 
     if (mainloop != NULL) {
         g_main_loop_unref(mainloop);
         mainloop = NULL;
     }
 
     pe_free_working_set(data_set);
     data_set = NULL;
     crm_exit(ec);
     return ec;
 }
 
 static void
 quit_main_loop(crm_exit_t ec)
 {
     exit_code = ec;
     if (mainloop != NULL) {
         GMainLoop *mloop = mainloop;
 
         mainloop = NULL; // Don't re-enter this block
         pcmk_quit_main_loop(mloop, 10);
         g_main_loop_unref(mloop);
     }
 }
 
 static gboolean
 resource_ipc_timeout(gpointer data)
 {
     // Start with newline because "Waiting for ..." message doesn't have one
     if (error != NULL) {
         g_clear_error(&error);
     }
 
     g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_TIMEOUT,
-                "Aborting because no messages received in %d seconds", MESSAGE_TIMEOUT_S);
+                _("Aborting because no messages received in %d seconds"), MESSAGE_TIMEOUT_S);
 
     quit_main_loop(CRM_EX_TIMEOUT);
     return FALSE;
 }
 
 static void
 controller_event_callback(pcmk_ipc_api_t *api, enum pcmk_ipc_event event_type,
                           crm_exit_t status, void *event_data, void *user_data)
 {
     switch (event_type) {
         case pcmk_ipc_event_disconnect:
             if (exit_code == CRM_EX_DISCONNECT) { // Unexpected
                 crm_info("Connection to controller was terminated");
             }
             quit_main_loop(exit_code);
             break;
 
         case pcmk_ipc_event_reply:
             if (status != CRM_EX_OK) {
                 out->err(out, "Error: bad reply from controller: %s",
                          crm_exit_str(status));
                 pcmk_disconnect_ipc(api);
                 quit_main_loop(status);
             } else {
                 if ((pcmk_controld_api_replies_expected(api) == 0)
                     && mainloop && g_main_loop_is_running(mainloop)) {
                     out->info(out, "... got reply (done)");
                     crm_debug("Got all the replies we expected");
                     pcmk_disconnect_ipc(api);
                     quit_main_loop(CRM_EX_OK);
                 } else {
                     out->info(out, "... got reply");
                 }
             }
             break;
 
         default:
             break;
     }
 }
 
 static void
 start_mainloop(pcmk_ipc_api_t *capi)
 {
     unsigned int count = pcmk_controld_api_replies_expected(capi);
 
     if (count > 0) {
         out->info(out, "Waiting for %u %s from the controller",
                   count, pcmk__plural_alt(count, "reply", "replies"));
         exit_code = CRM_EX_DISCONNECT; // For unexpected disconnects
         mainloop = g_main_loop_new(NULL, FALSE);
         g_timeout_add(MESSAGE_TIMEOUT_S * 1000, resource_ipc_timeout, NULL);
         g_main_loop_run(mainloop);
     }
 }
 
 static int
 compare_id(gconstpointer a, gconstpointer b)
 {
     return strcmp((const char *)a, (const char *)b);
 }
 
 static GList *
 build_constraint_list(xmlNode *root)
 {
     GList *retval = NULL;
     xmlNode *cib_constraints = NULL;
     xmlXPathObjectPtr xpathObj = NULL;
     int ndx = 0;
 
     cib_constraints = pcmk_find_cib_element(root, XML_CIB_TAG_CONSTRAINTS);
     xpathObj = xpath_search(cib_constraints, "//" XML_CONS_TAG_RSC_LOCATION);
 
     for (ndx = 0; ndx < numXpathResults(xpathObj); ndx++) {
         xmlNode *match = getXpathResult(xpathObj, ndx);
         retval = g_list_insert_sorted(retval, (gpointer) ID(match), compare_id);
     }
 
     freeXpathObject(xpathObj);
     return retval;
 }
 
 /* short option letters still available: eEJkKXyYZ */
 
 static GOptionEntry query_entries[] = {
     { "list", 'L', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
       "List all cluster resources with status",
       NULL },
     { "list-raw", 'l', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
       "List IDs of all instantiated resources (individual members\n"
       INDENT "rather than groups etc.)",
       NULL },
     { "list-cts", 'c', G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
       NULL,
       NULL },
     { "list-operations", 'O', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
       "List active resource operations, optionally filtered by\n"
       INDENT "--resource and/or --node",
       NULL },
     { "list-all-operations", 'o', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, list_cb,
       "List all resource operations, optionally filtered by\n"
       INDENT "--resource and/or --node",
       NULL },
     { "list-standards", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
       list_standards_cb,
       "List supported standards",
       NULL },
     { "list-ocf-providers", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
       list_providers_cb,
       "List all available OCF providers",
       NULL },
     { "list-agents", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
       list_agents_cb,
       "List all agents available for the named standard and/or provider",
       "STD:PROV" },
     { "list-ocf-alternatives", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
       list_alternatives_cb,
       "List all available providers for the named OCF agent",
       "AGENT" },
     { "show-metadata", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
       metadata_cb,
       "Show the metadata for the named class:provider:agent",
       "SPEC" },
     { "query-xml", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
       "Show XML configuration of resource (after any template expansion)",
       NULL },
     { "query-xml-raw", 'w', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
       "Show XML configuration of resource (before any template expansion)",
       NULL },
     { "get-parameter", 'g', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, get_param_prop_cb,
       "Display named parameter for resource (use instance attribute\n"
       INDENT "unless --meta or --utilization is specified)",
       "PARAM" },
     { "get-property", 'G', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, get_param_prop_cb,
       "Display named property of resource ('class', 'type', or 'provider') "
       "(requires --resource)",
       "PROPERTY" },
     { "locate", 'W', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
       "Show node(s) currently running resource",
       NULL },
     { "constraints", 'a', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
       "Display the location and colocation constraints that apply to a\n"
       INDENT "resource, and if --recursive is specified, to the resources\n"
       INDENT "directly or indirectly involved in those colocations.\n"
       INDENT "If the named resource is part of a group, or a clone or\n"
       INDENT "bundle instance, constraints for the collective resource\n"
       INDENT "will be shown unless --force is given.",
       NULL },
     { "stack", 'A', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
       "Equivalent to --constraints --recursive",
       NULL },
     { "why", 'Y', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, why_cb,
       "Show why resources are not running, optionally filtered by\n"
       INDENT "--resource and/or --node",
       NULL },
 
     { NULL }
 };
 
 static GOptionEntry command_entries[] = {
     { "validate", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
       validate_or_force_cb,
       "Validate resource configuration by calling agent's validate-all\n"
       INDENT "action. The configuration may be specified either by giving an\n"
       INDENT "existing resource name with -r, or by specifying --class,\n"
       INDENT "--agent, and --provider arguments, along with any number of\n"
       INDENT "--option arguments. An optional LEVEL argument can be given\n"
       INDENT "to control the level of checking performed.",
       "LEVEL" },
     { "cleanup", 'C', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, cleanup_refresh_cb,
       "If resource has any past failures, clear its history and fail\n"
       INDENT "count. Optionally filtered by --resource, --node, --operation\n"
       INDENT "and --interval (otherwise all). --operation and --interval\n"
       INDENT "apply to fail counts, but entire history is always clear, to\n"
       INDENT "allow current state to be rechecked. If the named resource is\n"
       INDENT "part of a group, or one numbered instance of a clone or bundled\n"
       INDENT "resource, the clean-up applies to the whole collective resource\n"
       INDENT "unless --force is given.",
       NULL },
     { "refresh", 'R', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, cleanup_refresh_cb,
       "Delete resource's history (including failures) so its current state\n"
       INDENT "is rechecked. Optionally filtered by --resource and --node\n"
       INDENT "(otherwise all). If the named resource is part of a group, or one\n"
       INDENT "numbered instance of a clone or bundled resource, the refresh\n"
       INDENT "applies to the whole collective resource unless --force is given.",
       NULL },
     { "set-parameter", 'p', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, set_delete_param_cb,
       "Set named parameter for resource (requires -v). Use instance\n"
       INDENT "attribute unless --meta or --utilization is specified.",
       "PARAM" },
     { "delete-parameter", 'd', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, set_delete_param_cb,
       "Delete named parameter for resource. Use instance attribute\n"
       INDENT "unless --meta or --utilization is specified.",
       "PARAM" },
     { "set-property", 'S', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, set_prop_cb,
       "Set named property of resource ('class', 'type', or 'provider') "
       "(requires -r, -t, -v)",
       "PROPERTY" },
 
     { NULL }
 };
 
 static GOptionEntry location_entries[] = {
     { "move", 'M', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
       "Create a constraint to move resource. If --node is specified,\n"
       INDENT "the constraint will be to move to that node, otherwise it\n"
       INDENT "will be to ban the current node. Unless --force is specified\n"
       INDENT "this will return an error if the resource is already running\n"
       INDENT "on the specified node. If --force is specified, this will\n"
       INDENT "always ban the current node.\n"
       INDENT "Optional: --lifetime, --promoted. NOTE: This may prevent the\n"
       INDENT "resource from running on its previous location until the\n"
       INDENT "implicit constraint expires or is removed with --clear.",
       NULL },
     { "ban", 'B', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
       "Create a constraint to keep resource off a node.\n"
       INDENT "Optional: --node, --lifetime, --promoted.\n"
       INDENT "NOTE: This will prevent the resource from running on the\n"
       INDENT "affected node until the implicit constraint expires or is\n"
       INDENT "removed with --clear. If --node is not specified, it defaults\n"
       INDENT "to the node currently running the resource for primitives\n"
       INDENT "and groups, or the promoted instance of promotable clones with\n"
       INDENT "promoted-max=1 (all other situations result in an error as\n"
       INDENT "there is no sane default).",
       NULL },
     { "clear", 'U', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, flag_cb,
       "Remove all constraints created by the --ban and/or --move\n"
       INDENT "commands. Requires: --resource. Optional: --node, --promoted,\n"
       INDENT "--expired. If --node is not specified, all constraints created\n"
       INDENT "by --ban and --move will be removed for the named resource. If\n"
       INDENT "--node and --force are specified, any constraint created by\n"
       INDENT "--move will be cleared, even if it is not for the specified\n"
       INDENT "node. If --expired is specified, only those constraints whose\n"
       INDENT "lifetimes have expired will be removed.",
       NULL },
     { "expired", 'e', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, expired_cb,
       "Modifies the --clear argument to remove constraints with\n"
       INDENT "expired lifetimes.",
       NULL },
     { "lifetime", 'u', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.move_lifetime,
       "Lifespan (as ISO 8601 duration) of created constraints (with\n"
       INDENT "-B, -M) see https://en.wikipedia.org/wiki/ISO_8601#Durations)",
       "TIMESPEC" },
     { "promoted", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE,
       &options.promoted_role_only,
       "Limit scope of command to promoted role (with -B, -M, -U). For\n"
       INDENT "-B and -M, previously promoted instances may remain\n"
       INDENT "active in the unpromoted role.",
       NULL },
 
     // Deprecated since 2.1.0
     { "master", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE,
       &options.promoted_role_only,
       "Deprecated: Use --promoted instead", NULL },
 
     { NULL }
 };
 
 static GOptionEntry advanced_entries[] = {
     { "delete", 'D', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, delete_cb,
       "(Advanced) Delete a resource from the CIB. Required: -t",
       NULL },
     { "fail", 'F', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, fail_cb,
       "(Advanced) Tell the cluster this resource has failed",
       NULL },
     { "restart", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, restart_cb,
       "(Advanced) Tell the cluster to restart this resource and\n"
       INDENT "anything that depends on it",
       NULL },
     { "wait", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, wait_cb,
       "(Advanced) Wait until the cluster settles into a stable state",
       NULL },
     { "digests", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, digests_cb,
       "(Advanced) Show parameter hashes that Pacemaker uses to detect\n"
       INDENT "configuration changes (only accurate if there is resource\n"
       INDENT "history on the specified node). Required: --resource, --node.\n"
       INDENT "Optional: any NAME=VALUE parameters will be used to override\n"
       INDENT "the configuration (to see what the hash would be with those\n"
       INDENT "changes).",
       NULL },
     { "force-demote", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
       validate_or_force_cb,
       "(Advanced) Bypass the cluster and demote a resource on the local\n"
       INDENT "node. Unless --force is specified, this will refuse to do so if\n"
       INDENT "the cluster believes the resource is a clone instance already\n"
       INDENT "running on the local node.",
       NULL },
     { "force-stop", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
       validate_or_force_cb,
       "(Advanced) Bypass the cluster and stop a resource on the local node",
       NULL },
     { "force-start", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
       validate_or_force_cb,
       "(Advanced) Bypass the cluster and start a resource on the local\n"
       INDENT "node. Unless --force is specified, this will refuse to do so if\n"
       INDENT "the cluster believes the resource is a clone instance already\n"
       INDENT "running on the local node.",
       NULL },
     { "force-promote", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
       validate_or_force_cb,
       "(Advanced) Bypass the cluster and promote a resource on the local\n"
       INDENT "node. Unless --force is specified, this will refuse to do so if\n"
       INDENT "the cluster believes the resource is a clone instance already\n"
       INDENT "running on the local node.",
       NULL },
     { "force-check", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
       validate_or_force_cb,
       "(Advanced) Bypass the cluster and check the state of a resource on\n"
       INDENT "the local node. An optional LEVEL argument can be given\n"
       INDENT "to control the level of checking performed.",
       "LEVEL" },
 
     { NULL }
 };
 
 static GOptionEntry addl_entries[] = {
     { "node", 'N', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.host_uname,
       "Node name",
       "NAME" },
     { "recursive", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.recursive,
       "Follow colocation chains when using --set-parameter or --constraints",
       NULL },
     { "resource-type", 't', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.rsc_type,
       "Resource XML element (primitive, group, etc.) (with -D)",
       "ELEMENT" },
     { "parameter-value", 'v', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.prop_value,
       "Value to use with -p",
       "PARAM" },
     { "meta", 'm', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, attr_set_type_cb,
       "Use resource meta-attribute instead of instance attribute\n"
       INDENT "(with -p, -g, -d)",
       NULL },
     { "utilization", 'z', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, attr_set_type_cb,
       "Use resource utilization attribute instead of instance attribute\n"
       INDENT "(with -p, -g, -d)",
       NULL },
     { "operation", 'n', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.operation,
       "Operation to clear instead of all (with -C -r)",
       "OPERATION" },
     { "interval", 'I', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.interval_spec,
       "Interval of operation to clear (default 0) (with -C -r -n)",
       "N" },
     { "class", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, class_cb,
       "The standard the resource agent conforms to (for example, ocf).\n"
       INDENT "Use with --agent, --provider, --option, and --validate.",
       "CLASS" },
     { "agent", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, agent_provider_cb,
       "The agent to use (for example, IPaddr). Use with --class,\n"
       INDENT "--provider, --option, and --validate.",
       "AGENT" },
     { "provider", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, agent_provider_cb,
       "The vendor that supplies the resource agent (for example,\n"
       INDENT "heartbeat). Use with --class, --agent, --option, and --validate.",
       "PROVIDER" },
     { "option", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, option_cb,
       "Specify a device configuration parameter as NAME=VALUE (may be\n"
       INDENT "specified multiple times). Use with --validate and without the\n"
       INDENT "-r option.",
       "PARAM" },
     { "set-name", 's', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.prop_set,
       "(Advanced) XML ID of attributes element to use (with -p, -d)",
       "ID" },
     { "nvpair", 'i', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.prop_id,
       "(Advanced) XML ID of nvpair element to use (with -p, -d)",
       "ID" },
     { "timeout", 'T', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, timeout_cb,
       "(Advanced) Abort if command does not finish in this time (with\n"
       INDENT "--restart, --wait, --force-*)",
       "N" },
     { "force", 'f', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.force,
       "If making CIB changes, do so regardless of quorum. See help for\n"
       INDENT "individual commands for additional behavior.",
       NULL },
     { "xml-file", 'x', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &options.xml_file,
       NULL,
       "FILE" },
     { "host-uname", 'H', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &options.host_uname,
       NULL,
       "HOST" },
 
     { NULL }
 };
 
 static void
 reset_options(void) {
     options.require_crmd = FALSE;
     options.require_node = FALSE;
 
     options.require_cib = TRUE;
     options.require_dataset = TRUE;
     options.require_resource = TRUE;
 
     options.find_flags = 0;
 }
 
 gboolean
 agent_provider_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     options.cmdline_config = TRUE;
     options.require_resource = FALSE;
 
     if (pcmk__str_eq(option_name, "--provider", pcmk__str_casei)) {
         pcmk__str_update(&options.v_provider, optarg);
     } else {
         pcmk__str_update(&options.v_agent, optarg);
     }
 
     return TRUE;
 }
 
 gboolean
 attr_set_type_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     if (pcmk__str_any_of(option_name, "-m", "--meta", NULL)) {
         options.attr_set_type = XML_TAG_META_SETS;
     } else if (pcmk__str_any_of(option_name, "-z", "--utilization", NULL)) {
         options.attr_set_type = XML_TAG_UTILIZATION;
     }
 
     return TRUE;
 }
 
 gboolean
 class_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     pcmk__str_update(&options.v_class, optarg);
     options.cmdline_config = TRUE;
     options.require_resource = FALSE;
     return TRUE;
 }
 
 gboolean
 cleanup_refresh_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     if (pcmk__str_any_of(option_name, "-C", "--cleanup", NULL)) {
         SET_COMMAND(cmd_cleanup);
     } else {
         SET_COMMAND(cmd_refresh);
     }
 
     options.require_resource = FALSE;
     if (getenv("CIB_file") == NULL) {
         options.require_crmd = TRUE;
     }
     options.find_flags = pe_find_renamed|pe_find_anon;
     return TRUE;
 }
 
 gboolean
 delete_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     SET_COMMAND(cmd_delete);
     options.require_dataset = FALSE;
     options.find_flags = pe_find_renamed|pe_find_any;
     return TRUE;
 }
 
 gboolean
 expired_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     options.clear_expired = TRUE;
     options.require_resource = FALSE;
     return TRUE;
 }
 
 static void
 get_agent_spec(const gchar *optarg)
 {
     options.require_cib = FALSE;
     options.require_dataset = FALSE;
     options.require_resource = FALSE;
     pcmk__str_update(&options.agent_spec, optarg);
 }
 
 gboolean
 list_agents_cb(const gchar *option_name, const gchar *optarg, gpointer data,
                GError **error)
 {
     SET_COMMAND(cmd_list_agents);
     get_agent_spec(optarg);
     return TRUE;
 }
 
 gboolean
 list_providers_cb(const gchar *option_name, const gchar *optarg, gpointer data,
                   GError **error)
 {
     SET_COMMAND(cmd_list_providers);
     get_agent_spec(optarg);
     return TRUE;
 }
 
 gboolean
 list_standards_cb(const gchar *option_name, const gchar *optarg, gpointer data,
                   GError **error)
 {
     SET_COMMAND(cmd_list_standards);
     options.require_cib = FALSE;
     options.require_dataset = FALSE;
     options.require_resource = FALSE;
     return TRUE;
 }
 
 gboolean
 list_alternatives_cb(const gchar *option_name, const gchar *optarg,
                      gpointer data, GError **error)
 {
     SET_COMMAND(cmd_list_alternatives);
     get_agent_spec(optarg);
     return TRUE;
 }
 
 gboolean
 metadata_cb(const gchar *option_name, const gchar *optarg, gpointer data,
             GError **error)
 {
     SET_COMMAND(cmd_metadata);
     get_agent_spec(optarg);
     return TRUE;
 }
 
 gboolean
 option_cb(const gchar *option_name, const gchar *optarg, gpointer data,
           GError **error)
 {
     char *name = NULL;
     char *value = NULL;
 
     if (pcmk__scan_nvpair(optarg, &name, &value) != 2) {
         return FALSE;
     }
     if (options.cmdline_params == NULL) {
         options.cmdline_params = pcmk__strkey_table(free, free);
     }
     g_hash_table_replace(options.cmdline_params, name, value);
     return TRUE;
 }
 
 gboolean
 fail_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     SET_COMMAND(cmd_fail);
     options.require_crmd = TRUE;
     options.require_node = TRUE;
     return TRUE;
 }
 
 gboolean
 flag_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     if (pcmk__str_any_of(option_name, "-U", "--clear", NULL)) {
         SET_COMMAND(cmd_clear);
         options.find_flags = pe_find_renamed|pe_find_anon;
     } else if (pcmk__str_any_of(option_name, "-B", "--ban", NULL)) {
         SET_COMMAND(cmd_ban);
         options.find_flags = pe_find_renamed|pe_find_anon;
     } else if (pcmk__str_any_of(option_name, "-M", "--move", NULL)) {
         SET_COMMAND(cmd_move);
         options.find_flags = pe_find_renamed|pe_find_anon;
     } else if (pcmk__str_any_of(option_name, "-q", "--query-xml", NULL)) {
         SET_COMMAND(cmd_query_xml);
         options.find_flags = pe_find_renamed|pe_find_any;
     } else if (pcmk__str_any_of(option_name, "-w", "--query-xml-raw", NULL)) {
         SET_COMMAND(cmd_query_raw_xml);
         options.find_flags = pe_find_renamed|pe_find_any;
     } else if (pcmk__str_any_of(option_name, "-W", "--locate", NULL)) {
         SET_COMMAND(cmd_locate);
         options.find_flags = pe_find_renamed|pe_find_anon;
 
     } else if (pcmk__str_any_of(option_name, "-a", "--constraints", NULL)) {
         SET_COMMAND(cmd_colocations);
         options.find_flags = pe_find_renamed|pe_find_anon;
 
     } else if (pcmk__str_any_of(option_name, "-A", "--stack", NULL)) {
         SET_COMMAND(cmd_colocations);
         options.find_flags = pe_find_renamed|pe_find_anon;
         options.recursive = TRUE;
     }
 
     return TRUE;
 }
 
 gboolean
 get_param_prop_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     if (pcmk__str_any_of(option_name, "-g", "--get-parameter", NULL)) {
         SET_COMMAND(cmd_get_param);
     } else {
         SET_COMMAND(cmd_get_property);
     }
 
     pcmk__str_update(&options.prop_name, optarg);
     options.find_flags = pe_find_renamed|pe_find_any;
     return TRUE;
 }
 
 gboolean
 list_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     if (pcmk__str_any_of(option_name, "-c", "--list-cts", NULL)) {
         SET_COMMAND(cmd_cts);
     } else if (pcmk__str_any_of(option_name, "-L", "--list", NULL)) {
         SET_COMMAND(cmd_list_resources);
     } else if (pcmk__str_any_of(option_name, "-l", "--list-raw", NULL)) {
         SET_COMMAND(cmd_list_instances);
     } else if (pcmk__str_any_of(option_name, "-O", "--list-operations", NULL)) {
         SET_COMMAND(cmd_list_active_ops);
     } else {
         SET_COMMAND(cmd_list_all_ops);
     }
 
     options.require_resource = FALSE;
     return TRUE;
 }
 
 gboolean
 set_delete_param_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     if (pcmk__str_any_of(option_name, "-p", "--set-parameter", NULL)) {
         SET_COMMAND(cmd_set_param);
     } else {
         SET_COMMAND(cmd_delete_param);
     }
 
     pcmk__str_update(&options.prop_name, optarg);
     options.find_flags = pe_find_renamed|pe_find_any;
     return TRUE;
 }
 
 gboolean
 set_prop_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     SET_COMMAND(cmd_set_property);
     options.require_dataset = FALSE;
     pcmk__str_update(&options.prop_name, optarg);
     options.find_flags = pe_find_renamed|pe_find_any;
     return TRUE;
 }
 
 gboolean
 timeout_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     options.timeout_ms = crm_get_msec(optarg);
     return TRUE;
 }
 
 gboolean
 validate_or_force_cb(const gchar *option_name, const gchar *optarg,
                      gpointer data, GError **error)
 {
     SET_COMMAND(cmd_execute_agent);
     if (options.operation) {
         g_free(options.operation);
     }
     options.operation = g_strdup(option_name + 2); // skip "--"
     options.find_flags = pe_find_renamed|pe_find_anon;
     if (options.override_params == NULL) {
         options.override_params = pcmk__strkey_table(free, free);
     }
 
     if (optarg != NULL) {
         if (pcmk__scan_min_int(optarg, &options.check_level, 0) != pcmk_rc_ok) {
             g_set_error(error, G_OPTION_ERROR, CRM_EX_INVALID_PARAM,
-                        "Invalid check level setting: %s", optarg);
+                        _("Invalid check level setting: %s"), optarg);
             return FALSE;
         }
     }
 
     return TRUE;
 }
 
 gboolean
 restart_cb(const gchar *option_name, const gchar *optarg, gpointer data,
            GError **error)
 {
     SET_COMMAND(cmd_restart);
     options.find_flags = pe_find_renamed|pe_find_anon;
     return TRUE;
 }
 
 gboolean
 digests_cb(const gchar *option_name, const gchar *optarg, gpointer data,
            GError **error)
 {
     SET_COMMAND(cmd_digests);
     options.find_flags = pe_find_renamed|pe_find_anon;
     if (options.override_params == NULL) {
         options.override_params = pcmk__strkey_table(free, free);
     }
     options.require_node = TRUE;
     options.require_dataset = TRUE;
     return TRUE;
 }
 
 gboolean
 wait_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     SET_COMMAND(cmd_wait);
     options.require_resource = FALSE;
     options.require_dataset = FALSE;
     return TRUE;
 }
 
 gboolean
 why_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
     SET_COMMAND(cmd_why);
     options.require_resource = FALSE;
     options.find_flags = pe_find_renamed|pe_find_anon;
     return TRUE;
 }
 
 static int
 ban_or_move(pcmk__output_t *out, pe_resource_t *rsc, const char *move_lifetime)
 {
     int rc = pcmk_rc_ok;
     pe_node_t *current = NULL;
     unsigned int nactive = 0;
 
     CRM_CHECK(rsc != NULL, return EINVAL);
 
     current = pe__find_active_requires(rsc, &nactive);
 
     if (nactive == 1) {
         rc = cli_resource_ban(out, options.rsc_id, current->details->uname, move_lifetime, NULL,
                               cib_conn, options.cib_options, options.promoted_role_only);
 
     } else if (pcmk_is_set(rsc->flags, pe_rsc_promotable)) {
         int count = 0;
         GList *iter = NULL;
 
         current = NULL;
         for(iter = rsc->children; iter; iter = iter->next) {
             pe_resource_t *child = (pe_resource_t *)iter->data;
             enum rsc_role_e child_role = child->fns->state(child, TRUE);
 
             if (child_role == RSC_ROLE_PROMOTED) {
                 count++;
                 current = pe__current_node(child);
             }
         }
 
         if(count == 1 && current) {
             rc = cli_resource_ban(out, options.rsc_id, current->details->uname, move_lifetime, NULL,
                                   cib_conn, options.cib_options, options.promoted_role_only);
 
         } else {
             rc = EINVAL;
             g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE,
-                        "Resource '%s' not moved: active in %d locations (promoted in %d).\n"
+                        _("Resource '%s' not moved: active in %d locations (promoted in %d).\n"
                         "To prevent '%s' from running on a specific location, "
                         "specify a node."
                         "To prevent '%s' from being promoted at a specific "
-                        "location, specify a node and the --promoted option.",
+                        "location, specify a node and the --promoted option."),
                         options.rsc_id, nactive, count, options.rsc_id, options.rsc_id);
         }
 
     } else {
         rc = EINVAL;
         g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE,
-                    "Resource '%s' not moved: active in %d locations.\n"
+                    _("Resource '%s' not moved: active in %d locations.\n"
                     "To prevent '%s' from running on a specific location, "
-                    "specify a node.",
+                    "specify a node."),
                     options.rsc_id, nactive, options.rsc_id);
     }
 
     return rc;
 }
 
 static void
 cleanup(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node)
 {
     int rc = pcmk_rc_ok;
 
     if (options.force == FALSE) {
         rsc = uber_parent(rsc);
     }
 
     crm_debug("Erasing failures of %s (%s requested) on %s",
               rsc->id, options.rsc_id, (options.host_uname? options.host_uname: "all nodes"));
     rc = cli_resource_delete(controld_api, options.host_uname, rsc, options.operation,
                              options.interval_spec, TRUE, data_set, options.force);
 
     if ((rc == pcmk_rc_ok) && !out->is_quiet(out)) {
         // Show any reasons why resource might stay stopped
         cli_resource_check(out, rsc, node);
     }
 
     if (rc == pcmk_rc_ok) {
         start_mainloop(controld_api);
     }
 }
 
 static int
 clear_constraints(pcmk__output_t *out, xmlNodePtr *cib_xml_copy)
 {
     GList *before = NULL;
     GList *after = NULL;
     GList *remaining = NULL;
     GList *ele = NULL;
     pe_node_t *dest = NULL;
     int rc = pcmk_rc_ok;
 
     if (!out->is_quiet(out)) {
         before = build_constraint_list(data_set->input);
     }
 
     if (options.clear_expired) {
         rc = cli_resource_clear_all_expired(data_set->input, cib_conn, options.cib_options,
                                             options.rsc_id, options.host_uname,
                                             options.promoted_role_only);
 
     } else if (options.host_uname) {
         dest = pe_find_node(data_set->nodes, options.host_uname);
         if (dest == NULL) {
             rc = pcmk_rc_node_unknown;
             if (!out->is_quiet(out)) {
                 g_list_free(before);
             }
             return rc;
         }
         rc = cli_resource_clear(options.rsc_id, dest->details->uname, NULL,
                                 cib_conn, options.cib_options, TRUE, options.force);
 
     } else {
         rc = cli_resource_clear(options.rsc_id, NULL, data_set->nodes,
                                 cib_conn, options.cib_options, TRUE, options.force);
     }
 
     if (!out->is_quiet(out)) {
         rc = cib_conn->cmds->query(cib_conn, NULL, cib_xml_copy, cib_scope_local | cib_sync_call);
         rc = pcmk_legacy2rc(rc);
 
         if (rc != pcmk_rc_ok) {
             g_set_error(&error, PCMK__RC_ERROR, rc,
-                        "Could not get modified CIB: %s\n", pcmk_strerror(rc));
+                        _("Could not get modified CIB: %s\n"), pcmk_strerror(rc));
             g_list_free(before);
             free_xml(*cib_xml_copy);
             *cib_xml_copy = NULL;
             return rc;
         }
 
         data_set->input = *cib_xml_copy;
         cluster_status(data_set);
 
         after = build_constraint_list(data_set->input);
         remaining = pcmk__subtract_lists(before, after, (GCompareFunc) strcmp);
 
         for (ele = remaining; ele != NULL; ele = ele->next) {
             out->info(out, "Removing constraint: %s", (char *) ele->data);
         }
 
         g_list_free(before);
         g_list_free(after);
         g_list_free(remaining);
     }
 
     return rc;
 }
 
 static int
 delete(void)
 {
     int rc = pcmk_rc_ok;
     xmlNode *msg_data = NULL;
 
     if (options.rsc_type == NULL) {
         rc = ENXIO;
         g_set_error(&error, PCMK__RC_ERROR, rc,
-                    "You need to specify a resource type with -t");
+                    _("You need to specify a resource type with -t"));
         return rc;
     }
 
     msg_data = create_xml_node(NULL, options.rsc_type);
     crm_xml_add(msg_data, XML_ATTR_ID, options.rsc_id);
 
     rc = cib_conn->cmds->remove(cib_conn, XML_CIB_TAG_RESOURCES, msg_data,
                                 options.cib_options);
     rc = pcmk_legacy2rc(rc);
     free_xml(msg_data);
     return rc;
 }
 
 static int
 list_agents(pcmk__output_t *out, const char *agent_spec)
 {
     int rc = pcmk_rc_ok;
     char *provider = strchr(agent_spec, ':');
     lrmd_t *lrmd_conn = NULL;
     lrmd_list_t *list = NULL;
 
     rc = lrmd__new(&lrmd_conn, NULL, NULL, 0);
     if (rc != pcmk_rc_ok) {
         goto error;
     }
 
     if (provider) {
         *provider++ = 0;
     }
 
     rc = lrmd_conn->cmds->list_agents(lrmd_conn, &list, agent_spec, provider);
 
     if (rc > 0) {
         rc = out->message(out, "agents-list", list, agent_spec, provider);
     } else {
         rc = pcmk_rc_error;
     }
 
 error:
     if (rc != pcmk_rc_ok) {
         if (provider == NULL) {
             g_set_error(&error, PCMK__RC_ERROR, rc,
-                        "No agents found for standard '%s'", agent_spec);
+                        _("No agents found for standard '%s'"), agent_spec);
         } else {
             g_set_error(&error, PCMK__RC_ERROR, rc,
-                        "No agents found for standard '%s' and provider '%s'",
+                        _("No agents found for standard '%s' and provider '%s'"),
                         agent_spec, provider);
         }
     }
 
     lrmd_api_delete(lrmd_conn);
     return rc;
 }
 
 static int
 list_providers(pcmk__output_t *out, const char *agent_spec)
 {
     int rc;
     const char *text = NULL;
     lrmd_t *lrmd_conn = NULL;
     lrmd_list_t *list = NULL;
 
     rc = lrmd__new(&lrmd_conn, NULL, NULL, 0);
     if (rc != pcmk_rc_ok) {
         goto error;
     }
 
     switch (options.rsc_cmd) {
         case cmd_list_alternatives:
             rc = lrmd_conn->cmds->list_ocf_providers(lrmd_conn, agent_spec, &list);
 
             if (rc > 0) {
                 rc = out->message(out, "alternatives-list", list, agent_spec);
             } else {
                 rc = pcmk_rc_error;
             }
 
             text = "OCF providers";
             break;
         case cmd_list_standards:
             rc = lrmd_conn->cmds->list_standards(lrmd_conn, &list);
 
             if (rc > 0) {
                 rc = out->message(out, "standards-list", list);
             } else {
                 rc = pcmk_rc_error;
             }
 
             text = "standards";
             break;
         case cmd_list_providers:
             rc = lrmd_conn->cmds->list_ocf_providers(lrmd_conn, agent_spec, &list);
 
             if (rc > 0) {
                 rc = out->message(out, "providers-list", list, agent_spec);
             } else {
                 rc = pcmk_rc_error;
             }
 
             text = "OCF providers";
             break;
         default:
             g_set_error(&error, PCMK__RC_ERROR, pcmk_rc_error, "Bug");
             lrmd_api_delete(lrmd_conn);
             return pcmk_rc_error;
     }
 
 error:
     if (rc != pcmk_rc_ok) {
         if (agent_spec != NULL) {
             rc = ENXIO;
             g_set_error(&error, PCMK__RC_ERROR, rc,
-                        "No %s found for %s", text, agent_spec);
+                        _("No %s found for %s"), text, agent_spec);
 
         } else {
             rc = ENXIO;
             g_set_error(&error, PCMK__RC_ERROR, rc,
-                        "No %s found", text);
+                        _("No %s found"), text);
         }
     }
 
     lrmd_api_delete(lrmd_conn);
     return rc;
 }
 
 static int
 populate_working_set(xmlNodePtr *cib_xml_copy)
 {
     int rc = pcmk_rc_ok;
 
     if (options.xml_file != NULL) {
         *cib_xml_copy = filename2xml(options.xml_file);
         if (*cib_xml_copy == NULL) {
             rc = pcmk_rc_cib_corrupt;
         }
     } else {
         rc = cib_conn->cmds->query(cib_conn, NULL, cib_xml_copy, cib_scope_local | cib_sync_call);
         rc = pcmk_legacy2rc(rc);
     }
 
     if (rc == pcmk_rc_ok) {
         data_set = pe_new_working_set();
         if (data_set == NULL) {
             rc = ENOMEM;
         } else {
             pe__set_working_set_flags(data_set,
                                       pe_flag_no_counts|pe_flag_no_compat);
             data_set->priv = out;
             rc = update_working_set_xml(data_set, cib_xml_copy);
         }
     }
 
     if (rc != pcmk_rc_ok) {
         free_xml(*cib_xml_copy);
         *cib_xml_copy = NULL;
         return rc;
     }
 
     cluster_status(data_set);
     return pcmk_rc_ok;
 }
 
 static int
 refresh(pcmk__output_t *out)
 {
     int rc = pcmk_rc_ok;
     const char *router_node = options.host_uname;
     int attr_options = pcmk__node_attr_none;
 
     if (options.host_uname) {
         pe_node_t *node = pe_find_node(data_set->nodes, options.host_uname);
 
         if (pe__is_guest_or_remote_node(node)) {
             node = pe__current_node(node->details->remote_rsc);
             if (node == NULL) {
                 rc = ENXIO;
                 g_set_error(&error, PCMK__RC_ERROR, rc,
-                            "No cluster connection to Pacemaker Remote node %s detected",
+                            _("No cluster connection to Pacemaker Remote node %s detected"),
                             options.host_uname);
                 return rc;
             }
             router_node = node->details->uname;
             attr_options |= pcmk__node_attr_remote;
         }
     }
 
     if (controld_api == NULL) {
         out->info(out, "Dry run: skipping clean-up of %s due to CIB_file",
                   options.host_uname? options.host_uname : "all nodes");
         rc = pcmk_rc_ok;
         return rc;
     }
 
     crm_debug("Re-checking the state of all resources on %s", options.host_uname?options.host_uname:"all nodes");
 
     rc = pcmk__attrd_api_clear_failures(NULL, options.host_uname, NULL,
                                         NULL, NULL, NULL, attr_options);
 
     if (pcmk_controld_api_reprobe(controld_api, options.host_uname,
                                   router_node) == pcmk_rc_ok) {
         start_mainloop(controld_api);
     }
 
     return rc;
 }
 
 static void
 refresh_resource(pcmk__output_t *out, pe_resource_t *rsc, pe_node_t *node)
 {
     int rc = pcmk_rc_ok;
 
     if (options.force == FALSE) {
         rsc = uber_parent(rsc);
     }
 
     crm_debug("Re-checking the state of %s (%s requested) on %s",
               rsc->id, options.rsc_id, (options.host_uname? options.host_uname: "all nodes"));
     rc = cli_resource_delete(controld_api, options.host_uname, rsc, NULL, 0,
                              FALSE, data_set, options.force);
 
     if ((rc == pcmk_rc_ok) && !out->is_quiet(out)) {
         // Show any reasons why resource might stay stopped
         cli_resource_check(out, rsc, node);
     }
 
     if (rc == pcmk_rc_ok) {
         start_mainloop(controld_api);
     }
 }
 
 static int
 set_property(void)
 {
     int rc = pcmk_rc_ok;
     xmlNode *msg_data = NULL;
 
     if (pcmk__str_empty(options.rsc_type)) {
         g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE,
-                    "Must specify -t with resource type");
+                    _("Must specify -t with resource type"));
         rc = ENXIO;
         return rc;
 
     } else if (pcmk__str_empty(options.prop_value)) {
         g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE,
-                    "Must supply -v with new value");
+                    _("Must supply -v with new value"));
         rc = ENXIO;
         return rc;
     }
 
     CRM_LOG_ASSERT(options.prop_name != NULL);
 
     msg_data = create_xml_node(NULL, options.rsc_type);
     crm_xml_add(msg_data, XML_ATTR_ID, options.rsc_id);
     crm_xml_add(msg_data, options.prop_name, options.prop_value);
 
     rc = cib_conn->cmds->modify(cib_conn, XML_CIB_TAG_RESOURCES, msg_data,
                                 options.cib_options);
     rc = pcmk_legacy2rc(rc);
     free_xml(msg_data);
 
     return rc;
 }
 
 static int
 show_metadata(pcmk__output_t *out, const char *agent_spec)
 {
     int rc = pcmk_rc_ok;
     char *standard = NULL;
     char *provider = NULL;
     char *type = NULL;
     char *metadata = NULL;
     lrmd_t *lrmd_conn = NULL;
 
     rc = lrmd__new(&lrmd_conn, NULL, NULL, 0);
     if (rc != pcmk_rc_ok) {
         g_set_error(&error, PCMK__RC_ERROR, rc,
-                    "Could not create executor connection");
+                    _("Could not create executor connection"));
         lrmd_api_delete(lrmd_conn);
         return rc;
     }
 
     rc = crm_parse_agent_spec(agent_spec, &standard, &provider, &type);
     rc = pcmk_legacy2rc(rc);
 
     if (rc == pcmk_rc_ok) {
         rc = lrmd_conn->cmds->get_metadata(lrmd_conn, standard,
                                            provider, type,
                                            &metadata, 0);
         rc = pcmk_legacy2rc(rc);
 
         if (metadata) {
             out->output_xml(out, "metadata", metadata);
             free(metadata);
         } else {
             /* We were given a validly formatted spec, but it doesn't necessarily
              * match up with anything that exists.  Use ENXIO as the return code
              * here because that maps to an exit code of CRM_EX_NOSUCH, which
              * probably is the most common reason to get here.
              */
             rc = ENXIO;
             g_set_error(&error, PCMK__RC_ERROR, rc,
                         _("Metadata query for %s failed: %s"),
                         agent_spec, pcmk_rc_str(rc));
         }
     } else {
         rc = ENXIO;
         g_set_error(&error, PCMK__RC_ERROR, rc,
                     _("'%s' is not a valid agent specification"), agent_spec);
     }
 
     lrmd_api_delete(lrmd_conn);
     return rc;
 }
 
 static void
 validate_cmdline_config(void)
 {
     // Cannot use both --resource and command-line resource configuration
     if (options.rsc_id != NULL) {
         g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE,
-                    "--resource cannot be used with --class, --agent, and --provider");
+                    _("--resource cannot be used with --class, --agent, and --provider"));
 
     // Not all commands support command-line resource configuration
     } else if (options.rsc_cmd != cmd_execute_agent) {
         g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE,
-                    "--class, --agent, and --provider can only be used with "
-                    "--validate and --force-*");
+                    _("--class, --agent, and --provider can only be used with "
+                    "--validate and --force-*"));
 
     // Not all of --class, --agent, and --provider need to be given.  Not all
     // classes support the concept of a provider.  Check that what we were given
     // is valid.
     } else if (pcmk__str_eq(options.v_class, "stonith", pcmk__str_none)) {
         if (options.v_provider != NULL) {
             g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE,
-                        "stonith does not support providers");
+                        _("stonith does not support providers"));
 
         } else if (stonith_agent_exists(options.v_agent, 0) == FALSE) {
             g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE,
-                        "%s is not a known stonith agent", options.v_agent ? options.v_agent : "");
+                        _("%s is not a known stonith agent"), options.v_agent ? options.v_agent : "");
         }
 
     } else if (resources_agent_exists(options.v_class, options.v_provider, options.v_agent) == FALSE) {
         g_set_error(&error, PCMK__EXITC_ERROR, CRM_EX_USAGE,
-                    "%s:%s:%s is not a known resource",
+                    _("%s:%s:%s is not a known resource"),
                     options.v_class ? options.v_class : "",
                     options.v_provider ? options.v_provider : "",
                     options.v_agent ? options.v_agent : "");
     }
 
     if (error != NULL) {
         return;
     }
 
     if (options.cmdline_params == NULL) {
         options.cmdline_params = pcmk__strkey_table(free, free);
     }
     options.require_resource = FALSE;
     options.require_dataset = FALSE;
     options.require_cib = FALSE;
 }
 
 static GOptionContext *
 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
     GOptionContext *context = NULL;
 
     GOptionEntry extra_prog_entries[] = {
         { "quiet", 'Q', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &(args->quiet),
           "Be less descriptive in output.",
           NULL },
         { "resource", 'r', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &options.rsc_id,
           "Resource ID",
           "ID" },
         { G_OPTION_REMAINING, 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING_ARRAY, &options.remainder,
           NULL,
           NULL },
 
         { NULL }
     };
 
     const char *description = "Examples:\n\n"
                               "List the available OCF agents:\n\n"
                               "\t# crm_resource --list-agents ocf\n\n"
                               "List the available OCF agents from the linux-ha project:\n\n"
                               "\t# crm_resource --list-agents ocf:heartbeat\n\n"
                               "Move 'myResource' to a specific node:\n\n"
                               "\t# crm_resource --resource myResource --move --node altNode\n\n"
                               "Allow (but not force) 'myResource' to move back to its original "
                               "location:\n\n"
                               "\t# crm_resource --resource myResource --clear\n\n"
                               "Stop 'myResource' (and anything that depends on it):\n\n"
                               "\t# crm_resource --resource myResource --set-parameter target-role "
                               "--meta --parameter-value Stopped\n\n"
                               "Tell the cluster not to manage 'myResource' (the cluster will not "
                               "attempt to start or stop the\n"
                               "resource under any circumstances; useful when performing maintenance "
                               "tasks on a resource):\n\n"
                               "\t# crm_resource --resource myResource --set-parameter is-managed "
                               "--meta --parameter-value false\n\n"
                               "Erase the operation history of 'myResource' on 'aNode' (the cluster "
                               "will 'forget' the existing\n"
                               "resource state, including any errors, and attempt to recover the"
                               "resource; useful when a resource\n"
                               "had failed permanently and has been repaired by an administrator):\n\n"
                               "\t# crm_resource --resource myResource --cleanup --node aNode\n\n";
 
     context = pcmk__build_arg_context(args, "text (default), xml", group, NULL);
     g_option_context_set_description(context, description);
 
     /* Add the -Q option, which cannot be part of the globally supported options
      * because some tools use that flag for something else.
      */
     pcmk__add_main_args(context, extra_prog_entries);
 
     pcmk__add_arg_group(context, "queries", "Queries:",
                         "Show query help", query_entries);
     pcmk__add_arg_group(context, "commands", "Commands:",
                         "Show command help", command_entries);
     pcmk__add_arg_group(context, "locations", "Locations:",
                         "Show location help", location_entries);
     pcmk__add_arg_group(context, "advanced", "Advanced:",
                         "Show advanced option help", advanced_entries);
     pcmk__add_arg_group(context, "additional", "Additional Options:",
                         "Show additional options", addl_entries);
     return context;
 }
 
 int
 main(int argc, char **argv)
 {
     xmlNode *cib_xml_copy = NULL;
     pe_resource_t *rsc = NULL;
     pe_node_t *node = NULL;
     int rc = pcmk_rc_ok;
 
     GOptionGroup *output_group = NULL;
     gchar **processed_args = NULL;
     GOptionContext *context = NULL;
 
     /*
      * Parse command line arguments
      */
 
     args = pcmk__new_common_args(SUMMARY);
     processed_args = pcmk__cmdline_preproc(argv, "GHINSTdginpstuvx");
     context = build_arg_context(args, &output_group);
 
     pcmk__register_formats(output_group, formats);
     if (!g_option_context_parse_strv(context, &processed_args, &error)) {
         exit_code = CRM_EX_USAGE;
         goto done;
     }
 
     pcmk__cli_init_logging("crm_resource", args->verbosity);
 
     rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
     if (rc != pcmk_rc_ok) {
         exit_code = CRM_EX_ERROR;
-        g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s",
+        g_set_error(&error, PCMK__EXITC_ERROR, exit_code, _("Error creating output format %s: %s"),
                     args->output_ty, pcmk_rc_str(rc));
         goto done;
     }
 
     pe__register_messages(out);
     crm_resource_register_messages(out);
     lrmd__register_messages(out);
     pcmk__register_lib_messages(out);
 
     out->quiet = args->quiet;
 
     crm_log_args(argc, argv);
 
     /*
      * Validate option combinations
      */
 
     // If the user didn't explicitly specify a command, list resources
     if (options.rsc_cmd == cmd_none) {
         options.rsc_cmd = cmd_list_resources;
         options.require_resource = FALSE;
     }
 
     // --expired without --clear/-U doesn't make sense
     if (options.clear_expired && (options.rsc_cmd != cmd_clear)) {
         exit_code = CRM_EX_USAGE;
-        g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "--expired requires --clear or -U");
+        g_set_error(&error, PCMK__EXITC_ERROR, exit_code, _("--expired requires --clear or -U"));
         goto done;
     }
 
     if ((options.remainder != NULL) && (options.override_params != NULL)) {
         // Commands that use positional arguments will create override_params
         for (gchar **s = options.remainder; *s; s++) {
             char *name = calloc(1, strlen(*s));
             char *value = calloc(1, strlen(*s));
             int rc = sscanf(*s, "%[^=]=%s", name, value);
 
             if (rc == 2) {
                 g_hash_table_replace(options.override_params, name, value);
 
             } else {
                 exit_code = CRM_EX_USAGE;
                 g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                            "Error parsing '%s' as a name=value pair",
+                            _("Error parsing '%s' as a name=value pair"),
                             argv[optind]);
                 free(value);
                 free(name);
                 goto done;
             }
         }
 
     } else if (options.remainder != NULL) {
         gchar **strv = NULL;
         gchar *msg = NULL;
         int i = 1;
         int len = 0;
 
         for (gchar **s = options.remainder; *s; s++) {
             len++;
         }
 
         CRM_ASSERT(len > 0);
 
         /* Add 1 for the strv[0] string below, and add another 1 for the NULL
          * at the end of the array so g_strjoinv knows when to stop.
          */
         strv = calloc(len+2, sizeof(char *));
         strv[0] = strdup("non-option ARGV-elements:\n");
 
         for (gchar **s = options.remainder; *s; s++) {
             strv[i] = crm_strdup_printf("[%d of %d] %s\n", i, len, *s);
             i++;
         }
 
         strv[i] = NULL;
 
         exit_code = CRM_EX_USAGE;
         msg = g_strjoinv("", strv);
         g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "%s", msg);
         g_free(msg);
 
         /* Don't try to free the last element, which is just NULL. */
         for(i = 0; i < len+1; i++) {
             free(strv[i]);
         }
         free(strv);
 
         goto done;
     }
 
     if (pcmk__str_eq(args->output_ty, "xml", pcmk__str_none)) {
         /* Kind of a hack to display XML lists using a real tag instead of <list>.  This just
          * saves from having to write custom messages to build the lists around all these things
          */
         switch (options.rsc_cmd) {
             case cmd_execute_agent:
             case cmd_list_resources:
             case cmd_query_xml:
             case cmd_query_raw_xml:
             case cmd_list_active_ops:
             case cmd_list_all_ops:
             case cmd_colocations:
                 pcmk__force_args(context, &error, "%s --xml-simple-list --xml-substitute", g_get_prgname());
                 break;
 
             default:
                 pcmk__force_args(context, &error, "%s --xml-substitute", g_get_prgname());
                 break;
         }
     } else if (pcmk__str_eq(args->output_ty, "text", pcmk__str_null_matches)) {
         if ((options.rsc_cmd == cmd_colocations) ||
             options.rsc_cmd == cmd_list_resources) {
             pcmk__force_args(context, &error, "%s --text-fancy", g_get_prgname());
         }
     }
 
     if (args->version) {
         out->version(out, false);
         goto done;
     }
 
     if (options.cmdline_config) {
         /* A resource configuration was given on the command line. Sanity-check
          * the values and set error if they don't make sense.
          */
         validate_cmdline_config();
         if (error != NULL) {
             exit_code = CRM_EX_USAGE;
             goto done;
         }
 
     } else if (options.cmdline_params != NULL) {
         // @COMPAT @TODO error out here when we can break backward compatibility
         g_hash_table_destroy(options.cmdline_params);
         options.cmdline_params = NULL;
     }
 
     if (options.require_resource && (options.rsc_id == NULL)) {
         exit_code = CRM_EX_USAGE;
         g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                    "Must supply a resource id with -r");
+                    _("Must supply a resource id with -r"));
         goto done;
     }
     if (options.require_node && (options.host_uname == NULL)) {
         exit_code = CRM_EX_USAGE;
         g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                    "Must supply a node name with -N");
+                    _("Must supply a node name with -N"));
         goto done;
     }
 
     /*
      * Set up necessary connections
      */
 
     if (options.force) {
         crm_debug("Forcing...");
         cib__set_call_options(options.cib_options, crm_system_name,
                               cib_quorum_override);
     }
 
     if (options.find_flags && options.rsc_id) {
         options.require_dataset = TRUE;
     }
 
     // Establish a connection to the CIB if needed
     if (options.require_cib) {
         cib_conn = cib_new();
         if ((cib_conn == NULL) || (cib_conn->cmds == NULL)) {
             exit_code = CRM_EX_DISCONNECT;
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                        "Could not create CIB connection");
+                        _("Could not create CIB connection"));
             goto done;
         }
         rc = cib_conn->cmds->signon(cib_conn, crm_system_name, cib_command);
         rc = pcmk_legacy2rc(rc);
         if (rc != pcmk_rc_ok) {
             exit_code = pcmk_rc2exitc(rc);
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                        "Could not connect to the CIB: %s", pcmk_rc_str(rc));
+                        _("Could not connect to the CIB: %s"), pcmk_rc_str(rc));
             goto done;
         }
     }
 
     /* Populate working set from XML file if specified or CIB query otherwise */
     if (options.require_dataset) {
         rc = populate_working_set(&cib_xml_copy);
         if (rc != pcmk_rc_ok) {
             exit_code = pcmk_rc2exitc(rc);
             goto done;
         }
     }
 
     // If command requires that resource exist if specified, find it
     if (options.find_flags && options.rsc_id) {
         rsc = pe_find_resource_with_flags(data_set->resources, options.rsc_id,
                                           options.find_flags);
         if (rsc == NULL) {
             exit_code = CRM_EX_NOSUCH;
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                        "Resource '%s' not found", options.rsc_id);
+                        _("Resource '%s' not found"), options.rsc_id);
             goto done;
         }
 
         /* The --ban, --clear, --move, and --restart commands do not work with
          * instances of clone resourcs.
          */
         if (strchr(options.rsc_id, ':') != NULL && pe_rsc_is_clone(rsc->parent) &&
             (options.rsc_cmd == cmd_ban || options.rsc_cmd == cmd_clear ||
              options.rsc_cmd == cmd_move || options.rsc_cmd == cmd_restart)) {
             exit_code = CRM_EX_INVALID_PARAM;
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                        "Cannot operate on clone resource instance '%s'", options.rsc_id);
+                        _("Cannot operate on clone resource instance '%s'"), options.rsc_id);
             goto done;
         }
     }
 
     // If user supplied a node name, check whether it exists
     if ((options.host_uname != NULL) && (data_set != NULL)) {
         node = pe_find_node(data_set->nodes, options.host_uname);
 
         if (node == NULL) {
             exit_code = CRM_EX_NOSUCH;
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                        "Node '%s' not found", options.host_uname);
+                        _("Node '%s' not found"), options.host_uname);
             goto done;
         }
     }
 
     // Establish a connection to the controller if needed
     if (options.require_crmd) {
         rc = pcmk_new_ipc_api(&controld_api, pcmk_ipc_controld);
         if (rc != pcmk_rc_ok) {
             exit_code = pcmk_rc2exitc(rc);
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                        "Error connecting to the controller: %s", pcmk_rc_str(rc));
+                        _("Error connecting to the controller: %s"), pcmk_rc_str(rc));
             goto done;
         }
         pcmk_register_ipc_callback(controld_api, controller_event_callback,
                                    NULL);
         rc = pcmk_connect_ipc(controld_api, pcmk_ipc_dispatch_main);
         if (rc != pcmk_rc_ok) {
             exit_code = pcmk_rc2exitc(rc);
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                        "Error connecting to the controller: %s", pcmk_rc_str(rc));
+                        _("Error connecting to the controller: %s"), pcmk_rc_str(rc));
             goto done;
         }
     }
 
     /*
      * Handle requested command
      */
 
     switch (options.rsc_cmd) {
         case cmd_list_resources: {
             GList *all = NULL;
             all = g_list_prepend(all, (gpointer) "*");
             rc = out->message(out, "resource-list", data_set,
                               pcmk_show_inactive_rscs | pcmk_show_rsc_only | pcmk_show_pending,
                               true, all, all, false);
             g_list_free(all);
 
             if (rc == pcmk_rc_no_output) {
                 rc = ENXIO;
             }
             break;
         }
 
         case cmd_list_instances:
             rc = out->message(out, "resource-names-list", data_set->resources);
 
             if (rc != pcmk_rc_ok) {
                 rc = ENXIO;
             }
 
             break;
 
         case cmd_list_standards:
         case cmd_list_providers:
         case cmd_list_alternatives:
             rc = list_providers(out, options.agent_spec);
             break;
 
         case cmd_list_agents:
             rc = list_agents(out, options.agent_spec);
             break;
 
         case cmd_metadata:
             rc = show_metadata(out, options.agent_spec);
             break;
 
         case cmd_restart:
             /* We don't pass data_set because rsc needs to stay valid for the
              * entire lifetime of cli_resource_restart(), but it will reset and
              * update the working set multiple times, so it needs to use its own
              * copy.
              */
             rc = cli_resource_restart(out, rsc, node, options.move_lifetime,
                                       options.timeout_ms, cib_conn,
                                       options.cib_options, options.promoted_role_only,
                                       options.force);
             break;
 
         case cmd_wait:
             rc = wait_till_stable(out, options.timeout_ms, cib_conn);
             break;
 
         case cmd_execute_agent:
             if (options.cmdline_config) {
                 exit_code = cli_resource_execute_from_params(out, NULL,
                     options.v_class, options.v_provider, options.v_agent,
                     options.operation, options.cmdline_params,
                     options.override_params, options.timeout_ms,
                     args->verbosity, options.force, options.check_level);
             } else {
                 exit_code = cli_resource_execute(rsc, options.rsc_id,
                     options.operation, options.override_params,
                     options.timeout_ms, cib_conn, data_set,
                     args->verbosity, options.force, options.check_level);
             }
             goto done;
 
         case cmd_digests:
             node = pe_find_node(data_set->nodes, options.host_uname);
             if (node == NULL) {
                 rc = pcmk_rc_node_unknown;
             } else {
                 rc = pcmk__resource_digests(out, rsc, node,
                                             options.override_params);
             }
             break;
 
         case cmd_colocations:
             rc = out->message(out, "locations-and-colocations", rsc, data_set,
                               options.recursive, (bool) options.force);
             break;
 
         case cmd_cts:
             rc = pcmk_rc_ok;
             g_list_foreach(data_set->resources, (GFunc) cli_resource_print_cts, out);
             cli_resource_print_cts_constraints(data_set);
             break;
 
         case cmd_fail:
             rc = cli_resource_fail(controld_api, options.host_uname,
                                    options.rsc_id, data_set);
             if (rc == pcmk_rc_ok) {
                 start_mainloop(controld_api);
             }
             break;
 
         case cmd_list_active_ops:
             rc = cli_resource_print_operations(options.rsc_id,
                                                options.host_uname, TRUE,
                                                data_set);
             break;
 
         case cmd_list_all_ops:
             rc = cli_resource_print_operations(options.rsc_id,
                                                options.host_uname, FALSE,
                                                data_set);
             break;
 
         case cmd_locate: {
             GList *nodes = cli_resource_search(rsc, options.rsc_id, data_set);
             rc = out->message(out, "resource-search-list", nodes, options.rsc_id);
             g_list_free_full(nodes, free);
             break;
         }
 
         case cmd_query_xml:
             rc = cli_resource_print(rsc, data_set, true);
             break;
 
         case cmd_query_raw_xml:
             rc = cli_resource_print(rsc, data_set, false);
             break;
 
         case cmd_why:
             if ((options.host_uname != NULL) && (node == NULL)) {
                 rc = pcmk_rc_node_unknown;
             } else {
                 rc = out->message(out, "resource-reasons-list",
                                   data_set->resources, rsc, node);
             }
             break;
 
         case cmd_clear:
             rc = clear_constraints(out, &cib_xml_copy);
             break;
 
         case cmd_move:
             if (options.host_uname == NULL) {
                 rc = ban_or_move(out, rsc, options.move_lifetime);
             } else {
                 rc = cli_resource_move(rsc, options.rsc_id, options.host_uname,
                                        options.move_lifetime, cib_conn,
                                        options.cib_options, data_set,
                                        options.promoted_role_only,
                                        options.force);
             }
 
             if (rc == EINVAL) {
                 exit_code = CRM_EX_USAGE;
                 goto done;
             }
 
             break;
 
         case cmd_ban:
             if (options.host_uname == NULL) {
                 rc = ban_or_move(out, rsc, options.move_lifetime);
             } else if (node == NULL) {
                 rc = pcmk_rc_node_unknown;
             } else {
                 rc = cli_resource_ban(out, options.rsc_id, node->details->uname,
                                       options.move_lifetime, NULL, cib_conn,
                                       options.cib_options,
                                       options.promoted_role_only);
             }
 
             if (rc == EINVAL) {
                 exit_code = CRM_EX_USAGE;
                 goto done;
             }
 
             break;
 
         case cmd_get_property:
             rc = out->message(out, "property-list", rsc, options.prop_name);
             if (rc == pcmk_rc_no_output) {
                 rc = ENXIO;
             }
 
             break;
 
         case cmd_set_property:
             rc = set_property();
             break;
 
         case cmd_get_param: {
             unsigned int count = 0;
             GHashTable *params = NULL;
             pe_node_t *current = pe__find_active_on(rsc, &count, NULL);
             bool free_params = true;
 
             if (count > 1) {
                 out->err(out, "%s is active on more than one node,"
                          " returning the default value for %s", rsc->id,
                          pcmk__s(options.prop_name, "unspecified property"));
                 current = NULL;
             }
 
             crm_debug("Looking up %s in %s", options.prop_name, rsc->id);
 
             if (pcmk__str_eq(options.attr_set_type, XML_TAG_ATTR_SETS, pcmk__str_casei)) {
                 params = pe_rsc_params(rsc, current, data_set);
                 free_params = false;
 
             } else if (pcmk__str_eq(options.attr_set_type, XML_TAG_META_SETS, pcmk__str_casei)) {
                 params = pcmk__strkey_table(free, free);
                 get_meta_attributes(params, rsc, current, data_set);
 
             } else {
                 params = pcmk__strkey_table(free, free);
                 pe__unpack_dataset_nvpairs(rsc->xml, XML_TAG_UTILIZATION, NULL, params,
                                            NULL, FALSE, data_set);
             }
 
             rc = out->message(out, "attribute-list", rsc, options.prop_name, params);
             if (free_params) {
                 g_hash_table_destroy(params);
             }
             break;
         }
 
         case cmd_set_param:
             if (pcmk__str_empty(options.prop_value)) {
                 exit_code = CRM_EX_USAGE;
                 g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                            "You need to supply a value with the -v option");
+                            _("You need to supply a value with the -v option"));
                 goto done;
             }
 
             /* coverity[var_deref_model] False positive */
             rc = cli_resource_update_attribute(rsc, options.rsc_id,
                                                options.prop_set,
                                                options.attr_set_type,
                                                options.prop_id,
                                                options.prop_name,
                                                options.prop_value,
                                                options.recursive, cib_conn,
                                                options.cib_options, data_set,
                                                options.force);
             break;
 
         case cmd_delete_param:
             /* coverity[var_deref_model] False positive */
             rc = cli_resource_delete_attribute(rsc, options.rsc_id,
                                                options.prop_set,
                                                options.attr_set_type,
                                                options.prop_id,
                                                options.prop_name, cib_conn,
                                                options.cib_options, data_set,
                                                options.force);
             break;
 
         case cmd_cleanup:
             if (rsc == NULL) {
                 rc = cli_cleanup_all(controld_api, options.host_uname,
                                      options.operation, options.interval_spec,
                                      data_set);
                 if (rc == pcmk_rc_ok) {
                     start_mainloop(controld_api);
                 }
             } else {
                 cleanup(out, rsc, node);
             }
             break;
 
         case cmd_refresh:
             if (rsc == NULL) {
                 rc = refresh(out);
             } else {
                 refresh_resource(out, rsc, node);
             }
             break;
 
         case cmd_delete:
             rc = delete();
             break;
 
         default:
             exit_code = CRM_EX_USAGE;
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                        "Unimplemented command: %d", (int) options.rsc_cmd);
+                        _("Unimplemented command: %d"), (int) options.rsc_cmd);
             goto done;
     }
 
     /* Convert rc into an exit code. */
     if (rc != pcmk_rc_ok && rc != pcmk_rc_no_output) {
         if (rc == pcmk_rc_no_quorum) {
             g_prefix_error(&error, "To ignore quorum, use the force option.\n");
         }
 
         exit_code = pcmk_rc2exitc(rc);
     }
 
     /*
      * Clean up and exit
      */
 
 done:
     /* When we get here, exit_code has been set one of two ways - either at one of
      * the spots where there's a "goto done" (which itself could have happened either
      * directly or by calling pcmk_rc2exitc), or just up above after any of the break
      * statements.
      *
      * Thus, we can use just exit_code here to decide what to do.
      */
     if (exit_code != CRM_EX_OK && exit_code != CRM_EX_USAGE) {
         if (error != NULL) {
             char *msg = crm_strdup_printf("%s\nError performing operation: %s",
                                           error->message, crm_exit_str(exit_code));
             g_clear_error(&error);
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "%s", msg);
             free(msg);
         } else {
             g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
-                        "Error performing operation: %s", crm_exit_str(exit_code));
+                        _("Error performing operation: %s"), crm_exit_str(exit_code));
         }
     }
 
     g_free(options.host_uname);
     g_free(options.interval_spec);
     g_free(options.move_lifetime);
     g_free(options.operation);
     g_free(options.prop_id);
     free(options.prop_name);
     g_free(options.prop_set);
     g_free(options.prop_value);
     g_free(options.rsc_id);
     g_free(options.rsc_type);
     free(options.agent_spec);
     free(options.v_agent);
     free(options.v_class);
     free(options.v_provider);
     g_free(options.xml_file);
     g_strfreev(options.remainder);
 
     if (options.override_params != NULL) {
         g_hash_table_destroy(options.override_params);
     }
 
     /* options.cmdline_params does not need to be destroyed here.  See the
      * comments in cli_resource_execute_from_params.
      */
 
     g_strfreev(processed_args);
     g_option_context_free(context);
 
     return bye(exit_code);
 }